给定val as: Seq[Int] = ...
很多时候我需要对两个连续的元素应用一个操作,例如
顺便说一下,我不喜欢
for (i <- 1 until as.size) {
// do something with as(i) and as(i - 1)
}
或另一个
as.tail.foldLeft((0, as.head)) { (acc, e) =>
// do something with acc._2 and e
// and try to not forget returning (_, e)
}
如何为这种情况编写更好的代码?
答案 0 :(得分:4)
您可zip
序列as
及其tail
:
for ((prev, curr) <- as zip as.tail) {
// do something with `prev` and `curr`
}
或者您可以使用sliding
:
for (window <- as.sliding(2)) {
val prev = window(0)
val curr = window(1)
// do something with `prev` and `curr`
}
答案 1 :(得分:1)
这是将序列头部提供给每个后续元素的一种方法。
val sq:Seq[Int] = Seq(. . .)
sq.headOption.fold(sq){hd =>
sq.tail.map(/*map() or fold() with the hd value*/)
}
请注意,对于1或0元素的集合,这是安全的。
答案 2 :(得分:0)
可以制作支持前一个元素的折叠。 安全的1或零元素集合。
def foldLeftWithPrevious[A, B](as: Seq[A], accumulator: B)(f: (B, A, A) => B): B = {
@scala.annotation.tailrec
def foldLeftInner(list2: Seq[A], previous: A, accumulator: B, f: (B, A, A) => B): B = {
if (list2.isEmpty) accumulator
else foldLeftInner(list2.tail, list2.head, f(accumulator, previous, list2.head), f)
}
if (as.length <= 1) accumulator
else foldLeftInner(as.tail, as.head, accumulator, f)
}
随意使用此代码段进行测试。
val foldLeftTest = Seq(1)
foldLeftWithPrevious(foldLeftTest, 0)((accum, previous, current) => {
println("accum = " + accum)
println("previous = " + previous)
println("current = " + current)
println("accum will be... " + accum + " + " + previous + " + " + current)
println("which is... " + (accum + previous + current))
accum + previous + current
})