Scala之集合上常見的函數式風格的操作彙總

目錄


正文

函數式編程對集合操作有一些通行的“叫法”,或者更像是一些“俚語”,它們的含義清晰明確,但是很難顧名思義,比如常見的“filter”,”map”,”flatMap”,“redue”等等。本文會把一些主要“俚語”詳細地解釋一下,同時給出一些參考示例。

“過濾”相關的操作

filter

解釋

設定一個判定結果爲布爾型的過濾條件,應用到集合的每一個元素上,返回的是集合裏所有滿足條件的元素構成的一個子集。

示例

scala> List.range(1, 11).filter (_ % 3 == 0)
res1: List[Int] = List(3, 6, 9)
scala> List("the", "quick", "brown", "fox", "jumped","over", "the", "lazy", "dog").filter(_.length == 3)
res2: List[String] = List(the, fox, the, dog)

partition

解釋

filter類型操作的一個變種,同樣是設定一個判定結果爲布爾型的過濾條件,應用到集合的每一個元素上,返回的是二個元素的Tuple, 第一個元素是所有滿足條件的元素構成一個集合,第二個元素是所有不滿足條件的元素構成一個集合。

示例

scala> List.range(1, 11).partition(_ % 3 == 0)
res3: (List[Int], List[Int]) = (List(3, 6, 9),List(1, 2, 4, 5, 7, 8, 10))

find

解釋

filter類型操作的一個變種,同樣是設定一個判定結果爲布爾型的過濾條件,返回集合中滿足條件的第一個元素。

示例

scala> List.range(1, 11).find(_ % 3 == 0)
res4: Option[Int] = Some(3)

takeWhile

解釋

filter類型操作的一個變種,同樣是設定一個判定結果爲布爾型的過濾條件,從集合的第一個元素開始,逐一判定元素是否符合條件,在遇到第一個不符合條件的元素後隨即結束過濾,返回的結果就是集合中前N個連續滿足條件的元素。

示例

scala> List(1, 2, 3, -4, 5, 6, 7, 8, 9, 10) takeWhile (_ > 0)
res5: List[Int] = List(1, 2, 3)

“映射”相關的操作

map

解釋

設定一個針對元素的“轉換”操作,應用到集合的每一個元素上,返回的結果是每個元素被轉換之後的新值組成的新集合。新的集合與舊集合大小一樣,但元素都是更新的,甚至類型也會發生變化。

示例

scala> List(1, 2, 3, 4, 5) map (_ + 1)
res6: List[Int] = List(2, 3, 4, 5, 6)

scala> List("the", "quick", "brown", "fox", "jumped","over", "the", "lazy", "dog").map(_.length)
res7: List[Int] = List(3, 5, 5, 3, 6, 4, 3, 4, 3)

flatMap

解釋

對於嵌套的集合(即集合中的元素還是集合),如果我們希望把每一個嵌套的子集“轉換”成一個新的子集,這時候就應該使用flatMap。

flatMap,不單單應用於集合,它代表着一種很普遍的操作:對於某種嵌套的數據結構,如果它的某個操作會把它的嵌套元素轉化或產生出新嵌套元素,則最終產生的將是一個“二維”的數據結構,也就是嵌套元素本身也是一個嵌套元素,這通常會讓這個產出的結果很不好用,一個必備的工作就是把這個二維”的數據結構“壓平”,重新拼接成一個一維的結構,這正是flatMap要做的事情。所以除了集合,Future也有這個方法,它就是在你使用map去轉換它的underlying時返回的又恰巧是一個Future,那麼這時你可以使用flatMap進行扁平化處理,得到的還是一個Future,而不是Future嵌套着Future。

示例

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_.toList)
res2: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_.reverse)
res3: List[Int] = List(3, 2, 1, 6, 5, 4, 9, 8, 7)

要特別注意的是flatMap使用的函數參數接收的是一個集合,返回的也是一個集合(GenTraversableOnce),你不能將一個集合元素“轉換”成單一的值,比如,你不能這樣做:

示例

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_ + 1)
<console>:12: error: type mismatch;
 found   : Int(1)
 required: String
       List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_ + 1)
                                                                      ^

如果你想針對嵌套集合中的每個元素進行裝換得到一個統一的集合,你可以這做做:

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)) flatMap (_.map(_+1))
res10: List[Int] = List(2, 3, 4, 5, 6, 7, 8, 9, 10)

下面是一個flatMap更加直觀的例子:

“扁平化”相關的操作

flatten

解釋

在函數式編程裏經常會出現嵌套的集合,我們需要頻繁地把這種嵌套的結構”壓“成”扁平“的單一集合,這個動作在函數式編程裏叫”flatten”。即:將所有嵌套的集合的元素一一取出逐一放置到一個集合中。

示例

scala> List(List(1, 2, 3), List(4, 5, 6), List(7, 8, 9)).flatten
res12: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> List("the", "quick", "brown", "fox", "jumped","over", "the", "lazy", "dog").flatten
res13: List[Char] = List(t, h, e, q, u, i, c, k, b, r, o, w, n, f, o, x, j, u, m, p, e, d, o, v, e, r, t, h, e, l, a, z, y, d, o, g)

“摺疊”相關的操作

reduceLeft

解釋

如果我們把集合看成是一張紙條,每一小段代表一個元素,那麼reduceLeft就將這張紙條從左向右”摺疊”,最前面的兩個元素會首先“重疊”在一起,這時會使用傳給reduceLeft的參數函數進行計算,返回的結果就像是已經摺疊在一起的兩段紙條,它們已經是一個疊加的狀態了,所以它,也就是上次重疊的結果會繼續做爲一個單一的值和下一個元素繼續“疊加”,直到摺疊到集合的最後一個元素。

示例

scala> List.range(1, 10).reduceLeft(_+_)
res0: Int = 45

reduceRight

解釋

同理,reduceRight就將這張紙條從右向左”摺疊”。要留心reduceRight的地方時:它的操作方向是從右到左,但是參數的順序卻並不是,而是依然第一參數是左邊的元素,第二參數是右邊的元素。我們可以通過一個示例來驗證:

示例

List.range(1, 10) reduceRight(_ - _)
// 8 - 9 = -1
// 7 - (-1) = 8
// 6 - 8 = -2
// 5 - (-2) = 7
// 4 - 7 = -3
// 3 - (-3) = 6
// 2 - 6 = -4
// 1 - (-4) = 5
// result: 5

foldLeft

解釋

與reduceLeft極爲相似,只是它開始操作的第一個元素是以參數的形式傳入的,而不是集合的第一個元素。

示例

scala> List.range(1, 10).foldLeft(1)(_+_)
res1: Int = 46

foldRight

解釋

與reduceRight極爲相似,只是它開始操作的第一個元素是以參數的形式傳入的,而不是集合的最後一個元素。

示例

scala> List.range(1, 10).foldRight(5)(_ - _)
res8: Int = 0

本文原文出處: http://blog.csdn.net/bluishglc/article/details/53320654 轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章