Scala 与前面的元素折叠
给定的Scala 与前面的元素折叠,scala,fold,Scala,Fold,给定的val为:Seq[Int]=… 很多时候,我需要对两个连续的元素应用一个操作,例如 顺便说一句,我不喜欢 for (i <- 1 until as.size) { // do something with as(i) and as(i - 1) } 如何为该场景编写更好的代码?您可以使用自己的尾部将序列作为: for ((prev, curr) <- as zip as.tail) { // do something with `prev` and `curr` }
val为:Seq[Int]=…
很多时候,我需要对两个连续的元素应用一个操作,例如
顺便说一句,我不喜欢
for (i <- 1 until as.size) {
// do something with as(i) and as(i - 1)
}
如何为该场景编写更好的代码?您可以使用自己的
尾部将序列作为:
for ((prev, curr) <- as zip as.tail) {
// do something with `prev` and `curr`
}
这里有一种方法可以将序列的开头提供给后续的每个元素
val sq:Seq[Int] = Seq(. . .)
sq.headOption.fold(sq){hd =>
sq.tail.map(/*map() or fold() with the hd value*/)
}
请注意,这对于1个或零个元素的集合是安全的。可以制作支持上一个元素的自己的折叠。
使用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)
}
您可以探索滑动,例如,将序列分成两对并映射到它们上as.sliding(2).map{case-prev+:next+:=>func(prev,next)}
我从未错过过这个函数。你确定你经常需要它吗?我想知道我们是否可以制作一个重载的foldLeft函数,它也传递上一个函数element@JordanCutler一个人不能简单地过载foldLeft
;)因为foldLeft
是一个数学常数,就像Pi
。但是你当然可以写一个融合的zipWithTailFoldLeft
,为什么不呢。只是似乎没有太多人错过它。这似乎有点不自然,因为不清楚数字2
来自何处。现在检查我的答案,让我知道你的意见。它声称接受签名中任意的Seq[A]
,但随后列出了与:
内部匹配的特定模式。对于所有非列表,它会产生匹配错误。此外:嵌套方法不需要块语法,因此f
不需要单独的变量列表;嵌套方法的名称对于8行方法来说似乎太长了;您可以添加@annotation.tailrec
,以明确该方法具有这个很好的属性.Fixed(除了“f不需要单独的变量列表”之外),尝试仍然理解您的意思)。Thank@AndreyTyukinI的意思是“参数列表”,抱歉:foldLeftInner(列表2:list[A],前一个:A,累加器:B,f:(B,A,A)=>B)
的括号更少,只有一个参数列表。无论如何,您都不使用块表示法,所以…注意!修复了x2:)现在它通常不会因匹配异常而崩溃,但签名仍然会调用impression,就好像它可以处理一样,因为Stream
是Seq
。一般来说,它看起来可以直接处理任何Seq
,而无需内部转换。嵌套方法似乎处于拒绝状态,因为它试图保持一种幻觉,即它可以使用一般的Seq
8]将Seq
更改为更严格的内容,或者以某种方式摆脱Nil
和:
。
val sq:Seq[Int] = Seq(. . .)
sq.headOption.fold(sq){hd =>
sq.tail.map(/*map() or fold() with the hd value*/)
}
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
})