下面是一个例子,在Scala集合 trait TraversableOnce 定义了 foldLeft def foldLeft[B](z: B)(op: (B, A) => B): B foldLeft 以下是该函数的一个用例: 从初值0开始, 这里 foldLeft 将函数 (m, n) => m + n 依次应用到列表中的每一个元素和之前累积的值上。 val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val res = numbers.foldLeft(0)((m, n) => m + n) print ,如下所示: val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) val numberFunc = numbers.foldLeft(List[Int]( 和 foldRight 可以按以下任意一种形式使用, val numbers = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) numbers.foldLeft(0)((sum
foldLeft是个尾递归方法。 1 foldLeft(List(1,2,3),0)((b,a) => a + b) //> res18: Int = 6 2 foldLeft(List(1,2,3),0){_ + : Int = 6 4 foldLeft(List(1,2,3),1){_ * _} //> res21: Int = 6 5 foldLeft(List(1,2,3 foldLeft(Cons(2,Cons(3,Nil)), (0 + 1)) {_ + _} 4 // foldLeft(Cons(3,Nil), ((0 + 1) + 2)) {_ + _} 5 // foldLeft(Nil, (((0 + 1) + 2) + 3)) {_ + _} 6 // (((0 + 1) + 2) + 3) + 0 = 6 除foldRight,foldLeft之外
我们先把用一个针对List的foldLeft实例来实现sum: 1 object listFoldLeft { 2 def foldLeft[A,B](xs: List[A])(b: B)(f: (B,A) => B):B = xs.foldLeft(b)(f) 3 } 4 def sum[A](xs: List[A])(implicit m: Monoid[A]): A = listFoldLeft.foldLeft [M[_]] { 2 def foldLeft[A,B](xs: M[A])(b: B)(f: (B,A) => B): B 3 } 4 object FoldLeft { 5 implicit object listFoldLeft extends FoldLeft[List] { 6 def foldLeft[A,B](xs: List[A])(b: B)(f:(B,A) => B):B = xs.foldLeft(b)(f) 7 } 8 } 9 def sum[M[_],A](xs: M[A])(implicit m: Monoid[A], fl: FoldLeft[
def foldMap[A, B](as: List[A])(mb: Monoid[B])(f: A => B): B = { 9 as.foldLeft(mb.zero)(( [A, B](as: IndexedSeq[A])(z: B)(f: (B, A) => B): B = { 20 as.foldLeft(z)(f) 21 } 22 override def foldMap[A, B](as: IndexedSeq[A])(mb: Monoid[B])(f: A => B): B = { 23 as.foldLeft [A, B](as: Stream[A])(z: B)(f: (B, A) => B): B = { 34 as.foldLeft(z)(f) 35 } 36 } 再看看 (r)(foldLeft(l)(z)(f))(f) 21 } 22 } 23 } 可以看出TreeFoldable的实现方式与List,Stream等串类数据类型有所不同
动手实现 在实现之前,我们先看下下面一段代码 function foldLeft($f, $zero, array $list) { if(empty($list)){ return else { $head = array_first($list); $tails = array_slice($list,1); return foldLeft 函数,实现了数组求和,函数foldLeft 有3个参数,第一个是一个二元函数,第二个是一个初值,第三个则是需要操作的集合,组合起来可以通过一张图来说明: ? foldLeft 让我们对foldLeft函数更进一步,看下他的函数类型 foldLeft :: (b -> a -> b) -> b -> t a -> b 此处(b -> a -> b)是函数$f的类型 3 "); }, ]; //foldl :: (b -> a -> b) -> b -> t a -> b $result = foldLeft
我们也可以用foldLeft来实现foldMap。 实际上我们同样可以用foldMap来实现foldRight和foldLeft: 1 def foldRight[A,B](la: List[A])(z: B)(f: (A,B) => B): B 2 def foldLeft[A,B](la: List[A])(z: B)(f: (A,B) => B): B 3 def foldMap[A,B](as: List[A])(m: Monoid[B])( f: A => B): B foldRight和foldLeft的f函数是(A,B) => B,如果用curry表达:A => (B => B),如果能把 A => ? 是从左边开始折叠,只需要采用endoComposeMonoid的镜像Monoid把op参数位置调换就行了: 1 def foldLeft[A,B](as: List[A])(z: B)(f: (A,
fold, foldLeft, foldRight: 计算一个单独的累计结果,带一个起始值。 scan, scanLeft, scanRight: 得到的是一个List。 reduceLeft, foldLeft, scanLeft: 从前到后线性计算。 reduceRight, foldRight, scanRight: 从后到前线性计算。 foldLeft是线性计算。 ") println("foldLeft: " + listAdd + " to: " + listAdd.foldLeft(100)(addOp(_, _))) println 100:1 101:2 103:3 106:4 110:5 foldLeft: List(1, 2, 3, 4, 5) to: 115 --- foldRight 5:100 4:105 3:109
本来想试着用Promise实现 List[Future[T]] 到 Future[List[T]]的转换,找到foldLeft这种方式。 如下: def sequence[T](fts: List[Future[T]]): Future[List[T]] = { fts.foldLeft(Future{ List.empty[T]}) Future[List[T]] = { val p = Promise[List[T]]() val result = p.success(List.empty[T]).future fts.foldLeft
._1).mapValues(_.foldLeft(0)(_+_._2)) foldLeft(0)(_+_._2)意思是((0+1)+1).... //折叠:有初始值(无特定顺序) val lst11=lst0.fold(100)((x,y)=>x+y) //折叠:有初始值(有特定顺序) val lst12=lst0.foldLeft(100
foldLeft() 与 reduce() 基本一致,区别在于 foldLeft() 保证在流中的顺序是从“左至右”的,不需要 fold 函数来关联。 另一方面,这是一个共容易懂的词汇:foldLeft() 仅代表一条循环的命令。循环的“起源”(即循环的初始化值)是一个完整的字母表(Seq.seq(alphabet))。
op 特性1:参数为一个匿名函数 特性2:规约结果一定是List元素的类型,所以是被经常使用的(相较于foldLeft) 对于List变量a scala> a res33: List[Int] = List scala> a.reduceLeft((x,y) => x+y) res31: Int = 10 可以使用下划线通配 scala> a.reduceLeft(_+_) res32: Int = 10 foldLeft op 特性1:使用柯里化定义 特性2:必须有初始值z 特性3:返回值是初始值z的类型,故不太使用 scala> a res33: List[Int] = List(1, 2, 3, 4) //使用foldLeft 进行元素的求和,并且初值为0 scala> a.foldLeft(0)((x,y) => x+y) res34: Int = 10 //使用通配符 scala> a.foldLeft(0)(_+_) res35 : Int = 10 //初值改变后的结果 scala> a.foldLeft(1)(_+_) res36: Int = 11 惰性求值的类型:Stream 流 //使用to或until来获取range
Failure(e) => println(s"Error processing future operations, error = ${e.getMessage}") } Future.foldLeft VS Future reduceLeft foldLeft 和 reduceLeft 都是用来从左到右做集合操作的,区别在于foldLeft可以提供默认值。 看下下面的例子: println(s"\nStep 3: Call Future.foldLeft to fold over futures results from left to right") val futureFoldLeft = Future.foldLeft(futureOperations)(0){ case (acc, someQty) => acc + someQty.getOrElse println(s"Error processing future operations, error = ${e.getMessage}") } 输出结果: Step 3: Call Future.foldLeft
var iteration = 1 var lastPlan = curPlan var continue = true while (continue) { //foldLeft 语法,形如A.foldLeft(B){(z,i)=>{dosomething() return C}} //curPlan是batch迭代的初始值 //case(plan,rule ) 中plan是batch中某个rule执行后返回的plan,继续投入batch中下个rule;rule是指batch中的某个rule对象 //整个foldLeft最后返回当前batch执行完之后生成的 plan curPlan = batch.rules.foldLeft(curPlan) { case (plan, rule) => val startTime
$1 (scala.collection) apply:157, TraversableOnce$$anonfun$foldLeft$1 (scala.collection) foreach:891, $1 (scala.collection) apply:157, TraversableOnce$$anonfun$foldLeft$1 (scala.collection) foreach:891, $1 (scala.collection) apply:157, TraversableOnce$$anonfun$foldLeft$1 (scala.collection) foreach:891, $1 (scala.collection) apply:157, TraversableOnce$$anonfun$foldLeft$1 (scala.collection) foreach:891, $1 (scala.collection) apply:157, TraversableOnce$$anonfun$foldLeft$1 (scala.collection) foreach:891,
总数的聚合 buffer1(1) = total1 + total2 // 2. map的聚合 buffer1(0) = map1.foldLeft(map2) { count) => CityRemark(cityName, count.toDouble / total) } // CityRemark("其他",1 - cityremarks.foldLeft (0D)(_+_.cityRatio)) cityRemarks :+= CityRemark("其他",cityRemarks.foldLeft(1D)(_ - _.cityRatio)) 总数的聚合 buffer1(1) = total1 + total2 // 2. map的聚合 buffer1(0) = map1.foldLeft(map2) { (0D)(_+_.cityRatio)) cityRemarks :+= CityRemark("其他",cityRemarks.foldLeft(1D)(_ - _.cityRatio))
._1).mapValues(_.foldLeft(0)(_ + _._2)) sender ! 100) } //计算最终结果 val count = resultList.flatMap(_.result).toList.groupBy(_._1).mapValues(_.foldLeft
= 0) res0: List[Int] = List(2, 3, 4, 5, 6, 7, 8, 9, 10) 8.foldLeft & foldRight scala> numbers.foldLeft (0)((m: Int, n: Int) => m + n) res0: Int = 55 scala> numbers.foldLeft(0) { (m: Int, n: Int) => println
11 final def foldRight1Opt(f: (A, => A) => A): Option[A] = F.foldRight1Opt(self)(f) 12 final def foldLeft [B](z: B)(f: (B, A) => B): B = F.foldLeft(self, z)(f) 13 final def foldMapLeft1Opt[B](z: A => B)(f: (B, A) => B): Option[B] = F.foldMapLeft1Opt(self)(z)(f) 14 final def foldLeft1Opt(f: (A, A) => A): Option[A] = F.foldLeft1Opt(self)(f) 15 final def foldRightM[G[_], B](z: => B)(f: (A, => B) => G[B] => B): (B, F[Unit]) = 2 runTraverseS(fa, z)(a => State.modify(f(_, a))) 3 4 override def foldLeft
(num1: Int, num2: Int): Int = { num1 - num2 } // 说明:折叠的理解和化简的运行机制几乎一样 // 理解 list.foldLeft (1)(minus) println(i6) // -19 i6 = (100 /: list4) (minus) // 等价于 list4.foldLeft(100)(minus) * 目的:理解 foldLeft 的用法 */ object Exercise01 { def main(args: Array[String]): Unit = { val sentence (arrBuf)(putArray) 理解成 sentence(arrBuf, A, A, ..., D, D).reduceLeft(putArray) println(sentence.foldLeft (map1)(charCount1)) // Map(A -> 10, B -> 8, C -> 5, D -> 7) // 将 sentence.foldLeft(map1)(charCount
主要关注点是fold和foldLeft版本之间的差别。fold,reduce和scan都限于返回与列表元素类型相同的一个值。foldLeft可以实现forall布尔操作,但是fold做不到。 // false是starting value // def foldLeft[B](z: B)(op: (B, A) ⇒ B): B scala> val included = List(46, 19 , 92).foldLeft(false) { (a, i) => (1) | if (a) a else (i == 19) | } included: Boolean = true