加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala:fold vs foldLeft

发布时间:2020-12-16 09:48:34 所属栏目:安全 来源:网络整理
导读:我试图理解如何fold和foldLeft和各自的reduce和reduceLeft工作。我使用fold和foldLeft作为我的例子 scala val r = List((ArrayBuffer(1,2,3,4),10))scala r.foldLeft(ArrayBuffer(1,4,5))((x,y) = x -- y._1)scala res28: scala.collection.mutable.ArrayBuf
我试图理解如何fold和foldLeft和各自的reduce和reduceLeft工作。我使用fold和foldLeft作为我的例子

scala> val r = List((ArrayBuffer(1,2,3,4),10))
scala> r.foldLeft(ArrayBuffer(1,4,5))((x,y) => x -- y._1)

scala> res28: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(5)

scala> r.fold(ArrayBuffer(1,y) => x -- y._1)
<console>:11: error: value _1 is not a member of Serializable with Equals
              r.fold(ArrayBuffer(1,y) => x -- y._1)

为什么fold不工作作为foldLeft?什么是可序列化与等于?我理解fold和foldLeft在参数通用类型方面有轻微不同的API签名。请指教。谢谢。

解决方法

方法折叠(最初添加用于并行计算)在foldLeft方面不如它可以应用于的类型强大。其签名是:

def fold[A1 >: A](z: A1)(op: (A1,A1) => A1): A1

这意味着进行折叠的类型必须是收集元素类型的超类型。

def foldLeft[B](z: B)(op: (B,A) => B): B

原因是fold可以并行实现,而foldLeft不能。这不仅是因为* Left部分,这意味着foldLeft从左到右顺序地,而且还因为操作符op不能组合并行计算的结果 – 它仅定义如何将聚合类型B与元素类型A组合,而不是如何组合类型B的两个聚集。折叠方法又定义了这一点,因为聚合类型A1必须是元素类型A的超类型,即A1> A。这个超类型关系允许同时折叠聚合和元素,以及组合聚合 – 两者与单个运算符。

但是,聚合和元素类型之间的这种超类型关系也意味着你的示例中的聚合类型A1应该是(ArrayBuffer [Int],Int)的超类型。由于您的聚合的零元素是ArrayBuffer [Int]类型的ArrayBuffer(1,2,4,5),所以聚合类型被推断为这两个类型的超类型 – 并且是Serializable with Equals,元组的上限和数组缓冲区。

一般来说,如果你想允许任意类型的并行折叠(这是无序的),你必须使用方法聚合,它需要定义如何组合两个聚合。在你的情况下:

r.aggregate(ArrayBuffer(1,5))({ (x,y) => x -- y._1 },(x,y) => x intersect y)

Btw,尝试使用reduce / reduceLeft编写您的示例 – 由于这两种方法具有的元素类型和聚合类型之间的超类型关系,您会发现它导致与您描述的类似的错误。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读