我正在尝试搜索特定字符的嵌套字符数组,然后从数组中返回字符的索引。
代码段
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循环..
答案 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{...}
语句引入过滤。
在理解中,a
是i
内的arr
数组,其中i
是第一个索引。 c
是j
中的a
个字符,其中j
是第二个索引。我使用iterator
以便可以动态评估indices
,而不需要因为for-comprehension而在幕后复制数组。最后,我调用toList
将indices
迭代器的结果计算到列表中。
返回类型List[(Int, Int)]
是对的列表。如果您在List( (1,2), (3,4) )
和i=1, j=2
找到目标而不是返回i=3, j=4
,则返回List(1,2,3,4)
会更有意义。
一般思考
尽量避免在scala中使用return
。您通常可以使用类似迭代器的方法处理集合,使用yield,然后通过调用toList
或toMap
或toWhatever
来评估结果。
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)
如果符合特定条件,您只返回List
(arr(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
}
顺便说一句,这可能会用更实用的方法重写,但这超出了这个问题的范围。