gpt4 book ai didi

scala - 惯用 "do until"集合更新

转载 作者:行者123 更新时间:2023-12-02 06:47:20 26 4
gpt4 key购买 nike

场景:

val col: IndexedSeq[Array[Char]] = for (i <- 1 to n) yield {
val x = for (j <- 1 to m) yield 'x'
x.toArray
}

这是一个相当简单的字符矩阵。 toArray 用于允许更新。

  var west = last.x - 1
while (west >= 0 && arr(last.y)(west) == '.') {
arr(last.y)(west) = ch;
west -= 1;
}

这会将所有 . 更新为 ch,直到找到非点字符。

一般来说,更新直到满足停止条件,步数未知。

它的惯用用法是什么?

结论

这是可行的,但这种权衡并不值得,当集合允许更新时,表达语法会损失大量性能。

最佳答案

您对“更干净、更惯用”的解决方案的愿望当然有点模糊,因为它留下了很大的主观空间。一般来说,我认为尾递归更新例程更惯用,但如果您更熟悉非函数式编程风格,它可能不会“更干净”。我想出了这个:

@tailrec
def update(arr:List[Char], replace:Char, replacement:Char, result:List[Char] = Nil):List[Char] = arr match {
case `replace` :: tail =>
update(tail, replace, replacement, replacement :: result)
case _ => result.reverse ::: arr
}

这采用内部序列之一(假设使用 List 更容易进行模式匹配,因为数组可以轻松转换为列表),并将 replace 字符替换为 替换递归地。

然后您可以使用 map 来更新外部序列,如下所示:

col.map { x => update(x, '.', ch) }
<小时/>

另一种更可重用的替代方案是编写您自己的 mapUntil,或者使用在补充库中实现的方案(Scalaz 可能有类似的东西)。我想出的一个看起来像这样:

def mapUntil[T](input:List[T])(f:(T => Option[T])) = {
@tailrec
def inner(xs:List[T], result:List[T]):List[T] = xs match {
case Nil => Nil
case head :: tail => f(head) match {
case None => (head :: result).reverse ::: tail
case Some(x) => inner(tail, x :: result)
}
}

inner(input, Nil)
}

它的作用与常规 map 调用相同,只不过它会在传递的函数返回 None 时立即停止,例如

mapUntil(List(1,2,3,4)) {
case x if x >= 3 => None
case x => Some(x-1)
}

将会导致

List[Int] = List(0, 1, 3, 4)
<小时/>

如果您想查看 Scalaz,this answer可能是一个很好的起点。

关于scala - 惯用 "do until"集合更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19657195/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com