文档章节

Scala:fold,foldLeft和foldRight区别与联系

月下独酌100
 月下独酌100
发布于 2016/04/22 15:41
字数 1020
阅读 199
收藏 1
  从本质上说,fold函数将一种格式的输入数据转化成另外一种格式返回。fold, foldLeft和foldRight这三个函数除了有一点点不同外,做的事情差不多。我将在下文解释它们的共同点并解释它们的不同点。
  我将从一个简单的例子开始,用fold计算一系列整型的和。

val numbers = List(5, 4, 8, 6, 2)
numbers.fold(0) { (z, i) =>
  z + i
}
// result = 25

  List中的fold方法需要输入两个参数:初始值以及一个函数。输入的函数也需要输入两个参数:累加值和当前item的索引。那么上面的代码片段发生了什么事?
  代码开始运行的时候,初始值0作为第一个参数传进到fold函数中,list中的第一个item作为第二个参数传进fold函数中。
  1、fold函数开始对传进的两个参数进行计算,在本例中,仅仅是做加法计算,然后返回计算的值;
  2、Fold函数然后将上一步返回的值作为输入函数的第一个参数,并且把list中的下一个item作为第二个参数传进继续计算,同样返回计算的值;
  3、第2步将重复计算,直到list中的所有元素都被遍历之后,返回最后的计算值,整个过程结束;
  4、这虽然是一个简单的例子,让我们来看看一些比较有用的东西。早在后面将会介绍foldLeft函数,并解释它和fold之间的区别,目前,你只需要想象foldLeft函数和fold函数运行过程一样。

  下面是一个简单的类和伴生类:

class Foo(val name: String, val age: Int, val sex: Symbol)

object Foo {
  def apply(name: String, age: Int, sex: Symbol) = new Foo(name, age, sex)
}
  假如我们有很多的Foo实例,并存在list中:

val fooList = Foo("Hugh Jass", 25, 'male) ::
              Foo("Biggus Dickus", 43, 'male) ::
              Foo("Incontinentia Buttocks", 37, 'female) ::
              Nil

  我们想将上面的list转换成一个存储[title] [name], [age]格式的String链表:

val stringList = fooList.foldLeft(List[String]()) { (z, f) =>
  val title = f.sex match {
    case 'male => "Mr."
    case 'female => "Ms."
  }
  z :+ s"$title ${f.name}, ${f.age}"
}

// stringList(0)
// Mr. Hugh Jass, 25

// stringList(2)
// Ms. Incontinentia Buttocks, 37
  和第一个例子一样,我们也有个初始值,这里是一个空的String list,也有一个操作函数。在本例中,我们判断了性别,并构造了我们想要的String,并追加到累加器中(这里是一个list)。
  fold, foldLeft, and foldRight之间的区别
  主要的区别是fold函数操作遍历问题集合的顺序。foldLeft是从左开始计算,然后往右遍历。foldRight是从右开始算,然后往左遍历。而fold遍历的顺序没有特殊的次序。来看下这三个函数的实现吧(在TraversableOnce特质里面实现)
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = foldLeft(z)(op)

def foldLeft[B](z: B)(op: (B, A) => B): B = {
  var result = z
  this.seq foreach (x => result = op(result, x))
  result
}

def foldRight[B](z: B)(op: (A, B) => B): B =
  reversed.foldLeft(z)((x, y) => op(y, x))

  由于fold函数遍历没有特殊的次序,所以对fold的初始化参数和返回值都有限制。在这三个函数中,初始化参数和返回值的参数类型必须相同。
  第一个限制是初始值的类型必须是list中元素类型的超类。在我们的例子中,我们的对List[Int]进行fold计算,而初始值是Int类型的,它是List[Int]的超类。
  第二个限制是初始值必须是中立的(neutral)。也就是它不能改变结果。比如对加法来说,中立的值是0;而对于乘法来说则是1,对于list来说则是Nil。

  顺便说下,其实foldLeft和foldRight函数还有两个缩写的函数:
 def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op)

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

scala> (0/:(1 to 100))(_+_)
res32: Int = 5050

scala> ((1 to 100):\0)(_+_)
res24: Int = 5050


本文转载自:http://www.iteblog.com/archives/1228

月下独酌100
粉丝 26
博文 220
码字总数 56475
作品 0
浦东
高级程序员
私信 提问
第十章 Scala 容器基础(二十):使用reduce和fold方法遍历集合的所有元素

Problem 你想要遍历有序集合的所有元素,并且随着你对集合元素的遍历,对比两个相邻的元素 Solution 使用reduceLeft, foldLeft, reduceRight, foldRight来遍历集合的元素,你的方法作用在相邻...

阿拉德大陆的魔法师
2016/04/16
1K
0
Traversing Mapping Filtering Folding Reducing

Traversing Mapping Filtering Folding Reducing Traversal 使用 foreach 遍历集合。foreach 是从特质 Iterable 混入而来的。 The signature of foreach is the following: trait Iterabl......

秋风醉了
2015/04/29
42
0
scala-常用函数介绍

欢迎大家关注: scala工具库 ,里面包含各种库的测试用例和使用说明文档 模式匹配 使用用模式匹配实现斐波那契 元组tuple 元组可以保存不同类型的值,不能通过名称获取字段,而是使用位置下标...

jacksu
2015/11/25
141
0
Scala 中 10 个超赞的集合操作函数

当我处理 Scala 集合时,我会进行两类操作:转换操作和聚合操作。第一种操作类型将集合转换为另一个集合,第二种操作类型返回某些类型的值。 本文我将集中介绍几个日常工作必备的 Scala 集合...

oschina
2016/12/28
6.7K
8
Scala类型系统——高级类类型(higher-kinded types)

高级类类型就是使用其他类型构造成为一个新的类型,因此也称为 类型构造器(type constructors)。它的语法和高阶函数(higher-order functions)相似,高阶函数就是将其它函数作为参数的函数;高...

Barudisshu
2016/06/13
906
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 早上儿子问我他是怎么来的

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @凉小生 :#今日歌曲推荐# 少点戾气,愿你和这个世界温柔以待。中岛美嘉的单曲《僕が死のうと思ったのは (曾经我也想过一了百了)》 《僕が死の...

小小编辑
今天
2.2K
14
Excption与Error包结构,OOM 你遇到过哪些情况,SOF 你遇到过哪些情况

Throwable 是 Java 中所有错误与异常的超类,Throwable 包含两个子类,Error 与 Exception 。用于指示发生了异常情况。 Java 抛出的 Throwable 可以分成三种类型。 被检查异常(checked Exc...

Garphy
今天
38
0
计算机实现原理专题--二进制减法器(二)

在计算机实现原理专题--二进制减法器(一)中说明了基本原理,现准备说明如何来实现。 首先第一步255-b运算相当于对b进行按位取反,因此可将8个非门组成如下图的形式: 由于每次做减法时,我...

FAT_mt
昨天
40
0
好程序员大数据学习路线分享函数+map映射+元祖

好程序员大数据学习路线分享函数+map映射+元祖,大数据各个平台上的语言实现 hadoop 由java实现,2003年至今,三大块:数据处理,数据存储,数据计算 存储: hbase --> 数据成表 处理: hive --> 数...

好程序员官方
昨天
61
0
tabel 中含有复选框的列 数据理解

1、el-ui中实现某一列为复选框 实现多选非常简单: 手动添加一个el-table-column,设type属性为selction即可; 2、@selection-change事件:选项发生勾选状态变化时触发该事件 <el-table @sel...

everthing
昨天
21
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部