簡單介紹一下姐呐,Scala語言中殿怜,foldLeft函數(shù)的三個使用場景:
- 列表內(nèi)數(shù)值的相加,作用相當(dāng)于sum;
- 變換后的Map集合有重復(fù)key值曙砂,并且需要根據(jù)key值合并
- 合并Map重復(fù)key值統(tǒng)計詞長度
場景一:列表數(shù)值相加头谜,先上代碼:
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函數(shù)此時的作用相當(dāng)于sum鸠澈。foldLeft后加圓括號柱告,圓括號中寫入初始值,因為要算整個List中每一個元素的和笑陈,因此际度,此時初始值為Int型的0。 之后的 (sum, i) => sum + i}
則表示涵妥,對于每一個List中的i元素乖菱,將i與sum相加,并將結(jié)果保存在sum中妹笆。foldLeft是從左往右遍歷块请,而與它相對應(yīng)的是函數(shù)foldRight,foldRight從右向左遍歷拳缠。
場景二:合并兩個Map墩新,重復(fù)key值相加,不覆蓋
在Scala的Map集合操作中窟坐,沒有直接將兩個Map根據(jù)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)
可見臣疑,直接暴力相加的話會覆蓋重復(fù)key的value值,如果想計算不同長度單詞的詞頻徙菠,單純將map中的key變換為key的長度讯沈,再對value進(jìn)行操作是不可取的。
可以使用foldLeft函數(shù)實現(xiàn):
scala> val map1 = Map("a" -> 1, "b" -> 2)
map1: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2)
scala> val map2 = Map("b" -> 4, "c" -> 8)
map2: scala.collection.immutable.Map[String,Int] = Map(b -> 4, c -> 8)
scala> val mergeMap = map1.foldLeft(map2) {
| case (newMap, (name, score)) =>
| newMap + (name -> (score + map2.getOrElse(name, 0)))
| }
mergeMap: scala.collection.immutable.Map[String,Int] = Map(b -> 6, c -> 8, a -> 1)
需要說明的是婿奔,newMap為定義的新map缺狠,name 和 score為模式匹配的新定義名稱问慎,這三個變量雖然都是新定義變量,但是都不需要提前val/var定義挤茄,可直接使用如叼。此時 newMap 的數(shù)據(jù)類型為 Map[String,Int]
,name的數(shù)據(jù)類型為String
穷劈,score的數(shù)據(jù)類型為Int
根據(jù)結(jié)果可知笼恰,經(jīng)過foldLeft之后,map相同key的value沒有被覆蓋歇终,而是相加合并了社证。
場景三: 合并Map重復(fù)key值統(tǒng)計詞長度
若一個Map中key為單詞,value為這個單詞的詞頻练湿,我們?nèi)粝敫鶕?jù)單詞的長度統(tǒng)計不同長度單詞的總詞頻猴仑,就會需要foldLeft函數(shù)出場
foldLeft可以對map的value值進(jìn)行相加,再這個場景下可以這樣寫:
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函數(shù)中傳入?yún)?shù)肥哎,即新map的初始值Map.empty[Int, Int]
, 然后根據(jù)case模式匹配辽俗,定義新map為newMap,對每一個原map中的值(fruit, count)
, 拿出fruit的單詞length篡诽,并且相加崖飘,賦到newMap中,就能得到我們想要的結(jié)果杈女。