scala搜索嵌套数组

时间:2013-02-03 12:55:46

标签: arrays scala search return

我正在尝试搜索特定字符的嵌套字符数组,然后从数组中返回字符的索引。

代码段

def search(target: Char, arr:Array[Array[Char]]): List[Int] = {
    for (i <- 0 until arr.length) { //search through first layer of array
    for (j <- 0 until arr(i).length) { //search through second layer of array
        if (arr(i)(j) == target) {
            val x = List(i,j)
            return x
        } }}}

但是,我从编译中得到一个错误,即该函数返回两个类型签名。错误讯息:

error: type mismatch;
 found   : Unit
 required: List[Int]
for (i <- 0 until arr.length) { //search through first layer of array
       ^

我在这里发现了两个相似的主题:found Unit: required Int. Why is the error not obvious?found: Unit required: Int - How to correct this?

但他们没有解决我面临的问题:我试图返回List,但编译器陷入了for循环..

5 个答案:

答案 0 :(得分:4)

似乎已经有很多答案,但我认为这是解决问题最惯用的方式:

守则

def search(target: Char, arr: Array[Array[Char]]): List[(Int, Int)] = {

    val indices = for{
        (a, i) <- arr.iterator.zipWithIndex
        (c, j) <- a.iterator.zipWithIndex
        if( c == target )
    } yield i -> j

    indices.toList

}

解释

在scala中,for-comprehensions是可嵌套的,因此只需添加另一行x <- y行就可以处理任何程度的嵌套数组。您可以使用if内的for{...}语句引入过滤。

在理解中,ai内的arr数组,其中i是第一个索引。 cj中的a个字符,其中j是第二个索引。我使用iterator以便可以动态评估indices,而不需要因为for-comprehension而在幕后复制数组。最后,我调用toListindices迭代器的结果计算到列表中。

返回类型List[(Int, Int)]是对的列表。如果您在List( (1,2), (3,4) )i=1, j=2找到目标而不是返回i=3, j=4,则返回List(1,2,3,4)会更有意义。

一般思考

尽量避免在scala中使用return。您通常可以使用类似迭代器的方法处理集合,使用yield,然后通过调用toListtoMaptoWhatever来评估结果。

scala集合API对许多这些情况也非常有帮助。如果您只想要与条件匹配的第一个项目,则可以使用myCollection.find(...)。浏览scala文档,了解您已经可以使用的各种便捷功能。

答案 1 :(得分:1)

我建议完全使用类似Java的方法。我不完全确定你的函数应该做什么,但是如果你想要一个嵌套数组中匹配的所有(x,y)索引的列表,你可以这样做:

def search(target: Char, array: Array[Array[Char]]): Seq[(Int, Int)] = {
  array.zipWithIndex.filter(_._1.contains(target)).map { xa =>
    xa._1.zipWithIndex.filter(_._1 == target).map(xb => (xa._2, xb._2)).toSeq
  }.flatten.toSeq
}

的行为如下:

val t = Array(
    Array('a', 'b', 'c'), 
    Array('b'), Array('c', 'a'), 
    Array('a', 'a', 'x', 'a')
)
println(search('a', t))
=> ((0,0), (2,1), (3,0), (3,1), (3,3))

答案 2 :(得分:1)

以下是我在二维数组中查找元素的第一个索引的解决方案: (如果你想找到所有索引,请将collectFirt替换为收集)

def search[T](target: T, arr: Array[Array[T]]): List[Int] = 
  arr.indices.collectFirst{
    case k if arr(k).contains(target) => 
      List(k, arr(k).indexWhere(_ == target)) 
  }.getOrElse(Nil)

测试:

scala> val t = Array(
     |     Array('a', 'b', 'c'),
     |     Array('b'), 
     |     Array('c', 'a'),
     |     Array('a', 'a', 'x', 'a')
     | )

scala> println(search('a', t))
List(0, 0)

scala> println(search('x', t))
List(3, 2)

scala> println(search('e', t))
List()

答案 3 :(得分:0)

如果符合特定条件,您只返回Listarr(i)(j) == target)。您必须为for comprehensions运行的案例定义返回值。 E.g。

def search(target: Char, arr:Array[Array[Char]]): List[Int] = {
  for (i <- 0 until arr.length) { //search through first layer of array
    for (j <- 0 until arr(i).length) { //search through second layer of array
      if (arr(i)(j) == target) {
        val x = List(i,j)
        return x
      }
    }
  }
  Nil  // not found
}

答案 4 :(得分:0)

如果第二个数组为空或if表达式的计算结果为false,则for循环本身将返回Unit。你可以重写它,这样如果nevers到达if-expression之后的代码,它就会返回null。

我也会忽略x的分配,这真的没有意义。

  def search(target: Char, arr:Array[Array[Char]]): List[Int] = 
  {
    for (i <- 0 until arr.length) 
    { //search through first layer of array
      for (j <- 0 until arr(i).length) 
      { //search through second layer of array
        if (arr(i)(j) == target) 
        {
          return List(i,j)
        } 
      }
    }
    Nil
  }

顺便说一句,这可能会用更实用的方法重写,但这超出了这个问题的范围。