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
  })