gpt4 book ai didi

Scala:查找并更新列表中的一个元素

转载 作者:行者123 更新时间:2023-12-02 08:03:45 24 4
gpt4 key购买 nike

我试图找到一种优雅的方式来做:

val l = List(1,2,3)

val (item, idx) = l.zipWithIndex.find(predicate)

val updatedItem = updating(item)

l.update(idx, updatedItem)

我可以一次完成所有操作吗?找到该项目,如果它存在,则替换为更新的值并将其保留在原位。

我可以:
l.map{ i => 
if (predicate(i)) {
updating(i)
} else {
i
}
}

但这很丑陋。

另一个复杂性是我只想更新匹配 predicate 的第一个元素。 .

编辑:尝试:
implicit class UpdateList[A](l: List[A]) {
def filterMap(p: A => Boolean)(update: A => A): List[A] = {
l.map(a => if (p(a)) update(a) else a)
}

def updateFirst(p: A => Boolean)(update: A => A): List[A] = {
val found = l.zipWithIndex.find { case (item, _) => p(item) }
found match {
case Some((item, idx)) => l.updated(idx, update(item))
case None => l
}
}
}

最佳答案

我不知道有什么方法可以在不使用可变变量的情况下通过一次集合来实现这一点。通过两次传递,您可以使用 foldLeft 来完成。如:

def updateFirst[A](list:List[A])(predicate:A => Boolean, newValue:A):List[A] = {
list.foldLeft((List.empty[A], predicate))((acc, it) => {acc match {
case (nl,pr) => if (pr(it)) (newValue::nl, _ => false) else (it::nl, pr)
}})._1.reverse
}

这个想法是 foldLeft允许通过迭代传递额外的数据。在这个特定的实现中,我将谓词更改为始终返回 false 的固定谓词。 .不幸的是,您无法构建 List以有效的方式从头部开始,因此这需要再次通过 reverse .

我相信很明显如何使用 map 的组合来做到这一点。和 var
备注 :性能 List.map与单次遍历列表相同,只是因为标准库在内部是可变的。特别是缺点类 ::被声明为
final case class ::[B](override val head: B, private[scala] var tl: List[B]) extends List[B] {

所以 tl实际上是 var这被 map 所利用以有效的方式从头部构建列表的实现。字段为 private[scala]所以你不能在标准库之外使用同样的技巧。不幸的是,我没有看到任何其他 API 调用允许使用此功能将问题的复杂性降低到单次传递。

关于Scala:查找并更新列表中的一个元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54015611/

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