我有以下Scala代码,命令式样式,我想知道是否存在功能样式的等效函数,避免使用return
:
def function(c: Char, vector: Vector[Vector[Char]]): (x:Int , y:Int) = {
for (x <- vector.indices)
for (y <- vector(x).indices)
if (vector(x)(y) == c)
return (x, y)
throw new NoSuchElementException
}
我想知道在不使用return
的情况下,是否有替代方案,效率与此相同。
答案 0 :(得分:2)
让我们从以下天真实施开始:
def function(c: Char, levelVector: Vector[Vector[Char]]): Option[(Int, Int)] = (
for {
(row, x) <- levelVector.zipWithIndex
(cell, y) <- row.zipWithIndex
if cell == c
} yield (x, y)
).headOption
(请注意,我在Option
中返回值而不是在没有匹配的情况下抛出异常,但如果您需要,可以添加.getOrElse(throw new NoSuchElementException)
原来的行为。)
在许多情况下,这种实现可能会很好,但它有点浪费,因为它会创建大量的中间集合,并检查每个元素,即使它找到匹配后也是如此。 (值得注意的是,您的命令式实施也会创建中间集合,但它们只是范围,而且它并不像这种天真的功能实现那么糟糕。)
以下版本可能更有效,但仍然避免使用return
:
def function(c: Char, levelVector: Vector[Vector[Char]]): Option[(Int, Int)] =
levelVector.view.zipWithIndex.map {
case (row, x) => (x, row.indexOf(c))
}.collectFirst {
case (x, y) if y >= 0 => (x, y)
}
在这里,我们使用view
来避免创建一堆中间集合,并collectFirst
在我们找到匹配项后停止检查。
如果您知道此方法的性能非常重要(可能不是这样),您仍应避免return
(这涉及在Scala的实现中抛出异常),而是使用var
和while
。对于这个简单的事情来说,这是非常合理的事情 - 只要确保你在方法中包含所有可变状态。
更多功能方向的下一步是尝试完全避免使用索引 - 经常有可能以这样的方式重新构建问题&#don 39;不需要它们,这样做通常会使你的程序更优雅(如果不是更高效)。