简单介绍一下,Scala语言中,foldLeft函数的两个使用场景:
- 列表内数值的相加,作用相当于sum;
- 变换后的Map集合有重复key值,并且需要根据key值合并
场景一:列表数值相加,先上代码:
scala> val list1 = List(1,2,3,4,5)
list1: List[Int] = List(1, 2, 3, 4, 5)
scala> println(list1.foldLeft(0) { (sum, i) => sum + i})
15
scala> println(list1.sum)
15
从代码中可以看出,foldLeft函数此时的作用相当于sum。foldLeft后加圆括号,圆括号中写入初始值,因为要算整个List中每一个元素的和,因此,此时初始值为Int型的0。 之后的 (sum, i) => sum + i}
则表示,对于每一个List中的i元素,将i与sum相加,并将结果保存在sum中。foldLeft是从左往右遍历,而与它相对应的是函数foldRight,foldRight从右向左遍历。
场景二: 合并Map重复key值
若一个Map中key为单词,value为这个单词的词频,我们若想根据单词的长度统计不同长度单词的总词频,就会需要foldLeft函数出场
在Scala的Map集合操作中,没有直接将两个Map根据key值合并value的操作,若是直接将两个Map相加,那么相同的key的值将会被后边的值覆盖,例如:
scala> val map1 = Map("aa" -> 1.0, "bb" -> 2.0)
map1: scala.collection.immutable.Map[String,Double] = Map(aa -> 1.0, bb -> 2.0)
scala> val map2 = Map("aa" -> 2.0, "cc" -> 4.0)
map2: scala.collection.immutable.Map[String,Double] = Map(aa -> 2.0, cc -> 4.0)
scala> println(map1 ++ map2)
Map(aa -> 2.0, bb -> 2.0, cc -> 4.0)
可见,直接暴力相加的话会覆盖重复key的value值,如果想计算不同长度单词的词频,单纯将map中的key变换为key的长度,再对value进行操作是不可取的。
foldLeft可以对map的value值进行相加,再这个场景下可以这样写:
scala> val wordsMap = Map("apple" -> 20, "pear" -> 10, "pineapple" -> 25, "grape" -> 30)
wordsMap: scala.collection.immutable.Map[String,Int] = Map(apple -> 20, pear -> 10, pineapple -> 25, grape -> 30)
scala> val wordFreqCount = wordsMap.foldLeft(Map.empty[Int, Int]) {
| case (newMap, (fruit, count)) =>
| newMap + (fruit.length -> (count + newMap.getOrElse(fruit.length, 0)))
| }
wordFreqCount: scala.collection.immutable.Map[Int,Int] = Map(5 -> 50, 4 -> 10, 9 -> 25)
首先在foldLeft函数中传入参数,即新map的初始值Map.empty[Int, Int]
, 然后根据case模式匹配,定义新map为newMap,对每一个原map中的值(fruit, count)
, 拿出fruit的单词length,并且相加,赋到newMap中,就能得到我们想要的结果。
网友评论