Scala的foldLeft和foldRight

原创 2014年04月11日 16:16:20

第一次看到/:以及:\这样的代码在别人的代码里,感觉很好奇,这是什么符号呢?

点进去看到方法的签名

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

def :\[B](z: B)(op: (A, B) => B): B = foldRight(z)(op)
OK,原来是foldLeft和foldRight的简写

foldLeft和foldRight直接翻译来向左折叠,向右折叠。


foldLeft

先来看定义:

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

方法接受2个参数,z和op,一个是B类型的参数,一个是返回B类型的函数。

在看到这个trait其实是TraversableOnce,可迭代的集合。

 def seq: TraversableOnce[A]

比如一个val listA = List(1,2,3)

listA其实是实现了TraversableOnce这个trait的。

我们可以直接使用:

scala> listA.foldLeft(0)((sum,i)=>sum+i)
res26: Int = 6

这个里面的0其实就是z返回值是Int类型即B类型

那么可以看出op这个函数返回值也需要是Int类型

可以看出

val result = z, 这里其实就是0,x=>result=op(result, x) , sum其实也是z

其实z就是返回值,this.seq在这里就是list,对list遍历,这里执行op函数。

这里我们执行的是sum+i,就是累加了1+2+3=6

foldRight

先看下定义:
def foldRight[B](z: B)(op: (A, B) => B): B =
    reversed.foldLeft(z)((x, y) => op(y, x))

这里多了一个reversed
 // for internal use
  protected[this] def reversed = {
    var elems: List[A] = Nil
    self.seq foreach (elems ::= _)
    elems
  }
内部使用的方法,意思就是
在list的head添加一个元素,就是在List[A]这个空列表的头部每次preappend一个元素。
如果是1,2,3那么最终就是3,2,1了,逆序,很好理解。
不过这个性能就。。。。我不敢恭维了,要逆序就要遍历一遍一个数组,然后操作再遍历一次。。。再操作。
但是如果你这样写,会发现很奇怪的结果:
scala> ((1 to 5)).foldRight(100)((sum,i)=>sum-i)
res48: Int = -97
接下来看重点了,参数顺序其实变了,我们原来的y是result
(x,y) => op(y,x)
这样写就对了:
scala> ((1 to 5)).foldRight(100)((i,sum)=>sum-i)
res49: Int = 85


总结一下,foldRight就是逆序集合,然后调用foldLeft. (Ps:我的scala版本2.9.3)

flodLeft的简写 /: 

这个是foldLeft的简写吧,个人理解。
如果我写一个累加的程序
scala> (0/:(1 to 100))(_+_)
res32: Int = 5050
其实是等价于
scala> (1 to 100).foldLeft(0)(_+_)
res33: Int = 5050

foldRight的简写 :\

这个就是foldRight的简写吧,个人理解。
如果我写一个递减的程序
scala> ((1 to 5):\100)((i,sum)=> sum-i)
res51: Int = 85


-EOF-

相关文章推荐

fold/foldLeft/foldRight区别和联系

1. fold介绍从本质上说,fold函数将一种格式的输入数据转化成另外一种格式返回。fold, foldLeft和foldRight这三个函数除了有一点点不同外,做的事情差不多。我将在下文解释它们的...

Scala: foldLeft和foldRight 实战

Scala: foldLeft和foldRight 实战 scala源代码: def /:[B](z: B)(op: (B, A) => B): B = foldLeft(z)(op) def ...

Scala 强大的集合数据操作示例

Scala是数据挖掘算法领域最有力的编程语言之一,语言本身是面向函数,这也符合了数据挖掘算法的常用场景:在原始数据集上应用一系列的变换,语言本身也对集合操作提供了众多强大的函数,本文将以List类型为...
  • pzw_0612
  • pzw_0612
  • 2015年05月23日 18:03
  • 57677

scala fold系列函数及 sparkRDD fold 操作解析

scala 的fold系列 函数用起来比较方便,这里对比总结一下。 fold fold 的定义: def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 fo...

Scala 中 10 个超赞的集合操作函数

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

SCALA学习笔记(一)

变量 获取变量的值是一个耗时的工作时,可以考虑使用lazy var. lazy val forLater = someTimeConsumingOperation() scala> va...

Scala的foldLeft和foldRight

Scala的foldLeft和foldRight FoldLeft 定义如下: override /*TraversableLike*/ def foldLeft[B](z: B...

【Scala】通过【foldLeft】来判断一个List是否是另一个List的子集

【Scala】通过【foldLeft】来判断一个List是否是另一个List的子集: val list1 = "电影 刘德华".split(" ", -1).toList val list2 = "醉...

scala基础38-foldLeft/foldRight/sortWith

object Test extends App{ //由初始值不停的向左执行f,结果5050 println((1 to 100).foldLeft(0)(_ + _)) //也可以这样写...

SCALA学习笔记(二)

SCALA学习笔记(二) SCALA学习笔记二 泛型在继承中的类型变化 Invariant Covariance Contravariance Covariance Contravarian...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Scala的foldLeft和foldRight
举报原因:
原因补充:

(最多只允许输入30个字)