2

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

代码片段

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
       ^

我在这里找到了两个类似的线程:find Unit: required Int. 为什么错误不明显?发现:所需单位:Int - 如何纠正这个问题?

但他们并没有解决我面临的问题:我正在尝试返回列表,但编译器卡在 for 循环中。

4

5 回答 5

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行来处理任何程度的嵌套数组。您可以iffor{...}.

在理解中,ai里面的第一个数组,第一个索引arr在哪里。是里面的第 th 个字符,其中是第二个索引。我使用这样可以即时评估,而无需因为理解而在幕后复制数组。最后,我调用将迭代器的结果评估为一个列表。icjajiteratorindicestoListindices

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

一般想法

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

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

于 2013-02-03T15:54:50.130 回答
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()
于 2013-02-03T14:18:28.927 回答
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))
于 2013-02-03T13:46:09.947 回答
0

List只有满足特定条件时才返回 a ( arr(i)(j) == target)。您必须为 for 理解运行的情况定义一个返回值。例如

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
}
于 2013-02-03T13:10:30.297 回答
0

如果第二个数组为空或 if 表达式的计算结果为 false,for 循环本身将返回 Unit。你可以重写它,如果它永远不会到达 if 表达式之后的代码,它会返回 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
  }

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

于 2013-02-03T13:11:10.727 回答