所以这可能不是解决问题的最佳方法,但我最初的想法是表达。 假设我有一个像
这样的列表List(List('a','b','c'),List('d','e','f'),List('h','i','j'))
我想找到一个字符的行和列,比如'e'
。
def findChar(letter: Char, list: List[List[Char]]): (Int, Int) =
for {
r <- (0 until list.length)
c <- (0 until list(r).length)
if list(r)(c) == letter
} yield (r, c)
如果有一种更优雅的方式,我会全神贯注,但我也想了解这有什么问题。特别是编译器给我的错误是
type mismatch; found : scala.collection.immutable.IndexedSeq[(Int, Int)] required: (Int, Int)
分配给r
的行上的。似乎抱怨我的迭代器与返回类型不匹配,但我不太明白为什么这是或者该怎么做...
答案 0 :(得分:2)
对于你的另一只耳朵,问题重复
How to capture inner matched value in indexWhere vector expression?
scala> List(List('a','b','c'),List('d','e','f'),List('h','i','j'))
res0: List[List[Char]] = List(List(a, b, c), List(d, e, f), List(h, i, j))
scala> .map(_ indexOf 'e').zipWithIndex.find(_._1 > -1)
res1: Option[(Int, Int)] = Some((1,1))
答案 1 :(得分:1)
在findChar
的签名中,您告诉编译器它返回(Int, Int)
。但是,您的for
表达式(由Scala推断)的结果为IndexedSeq[(Int, Int)]
,如错误消息所示。原因是(r, c)
在yield
表达式中的每个“迭代”后生成for
(即,您生成一系列结果,而不仅仅是单个结果)。
编辑:至于findChar
,您可以这样做:
def findChar(letter: Char, list: List[List[Char]]) = {
val r = list.indexWhere(_ contains letter)
val c = list(r).indexOf(letter)
(r, c)
}
这不是最有效的解决方案,但相对较短。
编辑或重复使用您原来的想法:
def findAll(letter: Char, list: List[List[Char]]) =
for {
r <- 0 until list.length
c <- 0 until list(r).length
if list(r)(c) == letter
} yield (r, c)
def findChar(c: Char, xs: List[List[Char]]) = findAll(c, xs).head
在这两种情况下,请注意,如果搜索的字母未包含在输入列表中,则会发生异常。
编辑:或者您自己编写递归函数,例如:
def findPos[A](c: A, list: List[List[A]]) = {
def aux(i: Int, xss: List[List[A]]) : Option[(Int, Int)] = xss match {
case Nil => None
case xs :: xss =>
val j = xs indexOf c
if (j < 0) aux(i + 1, xss)
else Some((i, j))
}
aux(0, list)
}
其中aux
是一个(本地定义的)辅助函数,它执行实际的递归(并记住我们在哪个子列表中,索引i
)。在此实现中,None
的结果表示搜索的元素不存在,而成功的结果可能返回Some((1, 1))
之类的内容。