我有一个要求,我必须在向量的向量中搜索一个字符。我写了一个很粗糙的方法。什么是在向量矢量中搜索元素的更好方法。
这是我的代码:
def search( xs: Vector[Vector[Char]], char: Char, rowIndex: Int): Pos = xs.headOption match {
case None => Pos(-1, -1)
case Some(row) => {
val tuple = searchHelper(row, char, 0)
if(tuple._1)
Pos(rowIndex, tuple._2)
else
search(xs.tail, char, rowIndex +1)
}
}
def searchHelper(xs: Vector[Char], char: Char, colIndex: Int): (Boolean, Int) = xs.headOption match {
case None => (false, colIndex)
case Some(col) =>
if(col == char)
(true, colIndex)
else
searchHelper(xs.tail, char, colIndex +1)
}
search(vector, c, 0)
这是输入:
val input =
"""ooo-------
|oSoooo----
|ooooooooo-
|-ooooooooo
|-----ooToo
|------ooo-""".stripMargin
val vector =
Vector(input.split("\n").map(str => Vector(str: _*)): _*)
val c = 'S'
答案 0 :(得分:3)
也许是这样的事情?
xs
.iterator
.zipWithIndex
.map { case (chars, idx) => (idx, chars.indexOf(c)) }
.collectFirst {
case (outer, inner) if(inner >= 0) => Pos(outer, inner)
}.getOrElse(Pos(-1, 1))
要解决注释中的问题:这是不多次遍历整个列表(甚至不是一次完整,只要它早先找到匹配)。 Scala迭代器非常精彩:你可以编写一系列调用,它在概念上看起来像是对整个列表的一系列顺序转换,但实际上是逐个元素地执行:第一个元素是从列表中提取,转换为一个元组(chars, 0)
,被馈送到map
,然后结果被发送到collectFirst
,如果条件匹配那里,它会停止并立即返回,否则,下一个元素被采用从列表中,制作成元组(chars, 1)
,馈送到.map
等等......
答案 1 :(得分:2)
如果更好,意味着更简洁,您可以尝试利用Scalas集合上的方法:
def search( xs: Vector[Vector[Char]], c: Char ): (Int, Int) = {
var innerIndex = -1
val outerIndex = xs.indexWhere { inner =>
innerIndex = inner.indexOf(c)
innerIndex > -1
}
(outerIndex, innerIndex)
}
这假设您只需要该角色的第一次出现。
只要innerIndex大于-1, indexWhere
就会终止。
也许是另一种可能性,它在你的递归方向上更多(并且没有可变的var),但也有最小的迭代次数:
@tailrec
def search(xs: Vector[Vector[Char]], c: Char, n: Int = 0): (Int, Int) = {
if (n > xs.size - 1) (-1, -1)
else
xs(n).indexOf(c) match {
case -1 => search(xs, c, n + 1)
case i => (n, i)
}
}