我正在尝试找到一种优雅的方式来实现以下操作:
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
}
}
}
if (!alreadyUpdated && predicate(i))
进行映射 - 您可以将所有内容封装在一个方法中,以避免暴露可变变量。对于完全不可变的解决方案,我会使用foldLeft
,其中您累积新的 List (向后) 和alreadyUpdated
标志,在折叠之后,您可以提取 List 然后反转它 - 但是它的复杂度为 2O(N) _(两次迭代)_,可能过于复杂。不确定是否有更好的方法,这就是为什么我没有回答的原因。 - Luis Miguel Mejía SuárezupdateFirst
方法到目前为止是最好的了? - Wonay