Traversing Mapping Filtering Folding Reducinges6
使用 foreach 遍歷集合。foreach 是從特質 Iterable 混入而來的。api
The signature of foreach is the following:app
trait Iterable[+A] { ... def foreach(f : (A) => Unit) : Unit = ... ... }
foreach 接收一個 函數類型的參數,因此是一個高階函數。對於map的遍歷,A 實際上是一個 元組。以下代碼示例,函數
//Traversal List(1, 2, 3, 4, 5) foreach { i => println("Int: " + i) } // map foreach val stateCapitals = Map("Alabama" -> "Montgomery", "Alaska" -> "Juneau", "Wyoming" -> "Cheyenne") stateCapitals foreach { kv => println(kv._1 + ": " + kv._2) }
集合的map操做會返回和原來集合相同大小的集合。map 做用於集合中的每個元素。ui
trait Iterable[+A] { ... def map[B] (f : (A) => B) : Iterable[B] = ... ... }
下面這個例子把原集合的key-value 中的value的類型給改變了,以下代碼,es5
val stateCapitals = Map( "Alabama" -> "Montgomery", "Alaska" -> "Juneau", "Wyoming" -> "Cheyenne") val lengths = stateCapitals map { kv => (kv._1, kv._2.length) } println(lengths) //map操做返回的集合Map(Alabama -> 10, Alaska -> 6, Wyoming -> 8)
結合映射[mapping]和扁平化[flattening]spa
flatMap的函數聲明scala
trait Iterable[+A] { ... def map[B] (f : (A) => B) : Iterable[B] = ... def flatMap[B] (f : (A) => Iterable[B] ) : Iterable[B] ... }
首先假設有一個這樣的情景:一個list集合,三個元素1,2,3,但願當集合元素是3 的時候,返回3.1,3.2,3.3,若是不是 3,集合元素乘以2。最終返回這樣的一個集合,(2,4,3.1,3.2,3.3);code
首先看一個map函數的例子,
blog
val list = List(1, 2, 3) val res = list.map(x => x match { case 3 => List(3.1, 3.2, 3.3) case _ => x * 2 }) println(res) //List(2, 4, List(3.1, 3.2, 3.3))
但結果不是這樣的,3.1, 3.2, 3.3 是用一個集合的形式返回的。若是用flatMap會怎麼樣呢?
val res2 = list.flatMap(x => x match { case 3 => List(3.1, 3.2, 3.3) case _ => List(x * 2) }) println(res2) //List(2, 4, 3.1, 3.2, 3.3)
flatMap是一種經常使用的組合子,結合映射[mapping]和扁平化[flattening]。 flatMap須要一個處理嵌套列表的函數,而後將結果串連起來。
val nestedNumbers = List(List(1, 2), List(3, 4)) val res5 = nestedNumbers.flatMap(x => x.map(_ * 2)) println(res5)//List(2, 4, 6, 8)
能夠把它看作是「先映射後扁平化」的快捷操做:
val res6 = nestedNumbers.map((x: List[Int]) => x.map(_ * 2)).flatten println(res6)//List(2, 4, 6, 8)
這個例子先調用map,而後能夠立刻調用flatten。
filter過濾集合中的元素,
以下代碼,過濾map集合中的元素
val stateCapitals = Map( "Alabama" -> "Montgomery", "Alaska" -> "Juneau", "Wyoming" -> "Cheyenne") val map2 = stateCapitals.filter(kv => kv._1 startsWith ("A")) println(map2)//Map(Alabama -> Montgomery, Alaska -> Juneau)
使用reduce函數,對集合中的兩個元素規約,直到最後一個元素,規約的順序不是必定的。
println(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20).reduce( (x: Int, y: Int) => { println(x, y); x + y })) //210
reduceRight 和 reduceLeft 肯定了規約的方向,以下,
println(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20).reduceRight( (x: Int, y: Int) => { println(x, y); x + y })) //210 println(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20).reduceLeft( (x: Int, y: Int) => { println(x, y); x + y })) //210
摺疊,容器的摺疊。
看以下例子,
val numbers = List(5, 4, 8, 6, 2) val res90 = numbers.fold(0) { (z, i) => { println(z, i) z + i } } println(res90)
運行並輸出,
(0,5)
(5,4)
(9,8)
(17,6)
(23,2)
25
最後把這個集合「摺疊」成25。
看一下 foldRight 和 foldLeft 的效果,
val res91 = numbers.foldRight(1) { (z, i) => { println(z, i) z + i } } val res92 = numbers.foldLeft(1) { (z, i) => { println(z, i) z + i } } println(res91) println(res92)
也能夠這樣調用,
val res93 = numbers.foldLeft(1)((z: Int, i: Int) => { println(z, i) z + i })
運行並輸出,foldRight 從右邊開始摺疊,輸入的初始參數爲 1 ,從右邊開始數,集合第一個元素是 2,相加獲得 3,而後又做爲下次摺疊的入參,和 集合的從右邊數的第二個元素相加。同理的 foldLeft。
(2,1)
(6,3)
(8,9)
(4,17)
(5,21)
26
(1,5)
(6,4)
(10,8)
(18,6)
(24,2)
26
還能夠參考如下文章:
http://wanghuanming.com/2014/12/Scala-highorder-function/
http://www.ituring.com.cn/article/131442
http://www.iteblog.com/archives/1228
http://www.tuicool.com/articles/Jviyim
==========END==========