十個(gè)驚人的Scala集合操作函數(shù)

十個(gè)驚人的Scala集合操作函數(shù)
當(dāng)我操作 Scala 集合時(shí),我一般會進(jìn)行兩類操作:轉(zhuǎn)換操作(transformation )和行動操作(actions)(有些人喜歡叫他為聚合操作)。第一種操作類型將集合轉(zhuǎn)換為另一個(gè)集合,第二種操作類型返回某些類型的值。

本文我將集中介紹幾個(gè)日常工作必備的 [Scala(https://www.iteblog.com/archives/tag/scala/) 集合函數(shù),如轉(zhuǎn)換函數(shù)和聚合函數(shù)。文章最后,我會展示如何結(jié)合這些函數(shù)以解決具體問題。

文章目錄
· 1?最大值和最小值

· 2?Filter

· 3?Flatten

· 4?歐拉圖函數(shù)(Euler Diagram函數(shù))

· 5?map列表元素

· 6?flatMap

· 7?對整個(gè)集合進(jìn)行條件檢查

· 8?對集合進(jìn)行分組

· 9?Fold

· 10?您最喜歡的函數(shù)

· 11?總結(jié)

十個(gè)驚人的scala集合操作函數(shù)
https://www.iteblog.com/archives/1946.html

最大值和最小值
  我們先從動作函數(shù)(
action function)開始。在序列中查找最大或最小值是一個(gè)極常見的需求,較常用于面試問題和算法。還記得 Java 中的代碼行嗎?如下:

int[] arr = {11, 2, 5, 1, 6, 3, 9};

int to = arr.length - 1;

int max = arr[0];

for (int i = 0; i < to; i++) {

    if (max < arr[i+1])

        max = arr[i+1];

}

  

System.out.println(max);

問題:怎么在List 中找到最大/最小值呢?

Scala 推薦了一個(gè)很贊的解決方案:

val numbers = Seq(11, 2, 5, 1, 6, 3, 9) 

 numbers.max //11 

numbers.min //1

但實(shí)際操作的數(shù)據(jù)更加復(fù)雜。下面我們介紹一個(gè)更高級的例子,其中包含一個(gè)書的序列(查看源代碼案例)。

case class Book(title: String, pages: Int)

 val books = Seq(

  Book("Future of Scala developers", 85),

  Book("Parallel algorithms", 240),

  Book("Object Oriented Programming", 130),

  Book("Mobile Development", 495)

)

  

//Book(Mobile Development,495)

books.maxBy(book => book.pages)

  

//Book(Future of Scala developers,85)

books.minBy(book => book.pages)

如上所示,
minBy & maxBy方法解決了復(fù)雜數(shù)據(jù)的問題。你只需選擇決定數(shù)據(jù)最大或最小的屬性。

Filter
你過濾過集合嗎?比如,篩選價(jià)格大于10美元的條目,或挑選年齡在24歲以下員工等,所有這些操作屬于過濾。
讓我們舉例說明:過濾一個(gè)數(shù)字List,只獲取奇數(shù)的元素。

val numbers = Seq(1,2,3,4,5,6,7,8,9,10)

 numbers.filter(n **=**> n **%** 2 **==** 0)

然后加大難度,我想獲取頁數(shù)大于
120頁的書。

val books = Seq(

  Book("Future of Scala developers", 85),

  Book("Parallel algorithms", 240),

  Book("Object Oriented Programming", 130),

  Book("Mobile Development", 495)

)

  

books.filter(book => book.pages >= 120)

實(shí)際上,過濾是一個(gè)轉(zhuǎn)換類型的方法,但是比運(yùn)用min和max方法簡單。

還有一個(gè)與filter類似的方法是filterNot。它的名字就體現(xiàn)了它的作用。如果你還是不了解它的實(shí)際用途,你可以在一個(gè)示例中,用filterNot替換filter 方法。

Flatten
我想大多數(shù)朋友都沒聽說過這個(gè)功能。其實(shí)它很好理解,我們來舉例說明:

val abcd = Seq('a', 'b', 'c', 'd')

val efgj = Seq('e', 'f', 'g', 'h')

val ijkl = Seq('i', 'j', 'k', 'l')

val mnop = Seq('m', 'n', 'o', 'p')

val qrst = Seq('q', 'r', 's', 't')

val uvwx = Seq('u', 'v', 'w', 'x')

val yz = Seq('y', 'z')

val alphabet = Seq(abcd, efgj, ijkl, mnop, qrst, uvwx, yz)

// List(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z)

alphabet.flatten

當(dāng)有一個(gè)集合的集合,然后你想對這些集合的所有元素進(jìn)行操作時(shí),就會用到
flatten。

歐拉圖函數(shù)(Euler Diagram函數(shù))
不要緊張!接下來的操作大家都熟知:差集、交集和并集。以下示例能很好地解釋
Euler Diagram 函數(shù):

val num1 = Seq(1, 2, 3, 4, 5, 6)

val num2 = Seq(4, 5, 6, 7, 8, 9)

//List(1, 2, 3)

num1.diff(num2)

//List(4, 5, 6)

num1.intersect(num2)

//List(1, 2, 3, 4, 5, 6, 4, 5, 6, 7, 8, 9)

num1.union(num2)

上述示例中的 union保留了重復(fù)的元素。如果我們不需要重復(fù)怎么辦?這時(shí)可以使用
distinct函數(shù):

//List(1, 2, 3, 4, 5, 6, 7, 8, 9)

num1.union(num2).distinct

下面是上述功能的圖示:

map列表元素
map 是 Scala 集合最常用的一個(gè)函數(shù)。它的功能十分強(qiáng)大:

val numbers = Seq(1,2,3,4,5,6)

//List(2, 4, 6, 8, 10, 12)

numbers.map(n **=**> n * 2)

val chars = Seq('a', 'b', 'c', 'd')

//List(A, B, C, D)

chars.map(ch **=**> ch.toUpper)

map 函數(shù)的邏輯是遍歷集合中的元素并對每個(gè)元素調(diào)用函數(shù)。你也可以不調(diào)用任何函數(shù),保持返回元素本身,但這樣 map無法發(fā)揮作用,因?yàn)槟阍谟成溥^后得到的是同樣的集合。

flatMap
我很難具體說明flatMap 的使用場合,因?yàn)楹芏嗖煌那闆r下都會用到 flatMap。如果大家仔細(xì)觀察,就會發(fā)現(xiàn)flatMap 是由下列這兩個(gè)函數(shù)組成的:map & flatten
現(xiàn)在,假設(shè)我們想知道字母表中的大寫字母和小寫字母的排列情況:

val abcd = Seq('a', 'b', 'c', 'd')

//List(A, a, B, b, C, c, D, d)

abcd.flatMap(ch **=**> List(ch.toUpper, ch))

因?yàn)檫@篇文章是關(guān)于集合功能的介紹,所以此處略過
Future 和 Option 的示例。

對整個(gè)集合進(jìn)行條件檢查
有一個(gè)場景大家都知道,即確保集合中所有元素都要符合某些要求,如果有哪怕一個(gè)元素不符合條件,就需要進(jìn)行一些處理:

val numbers = Seq(3, 7, 2, 9, 6, 5, 1, 4, 2)

//ture

numbers.forall(n **=**> n < 10)

//false

numbers.forall(n **=**> n > 5)

而forall 函數(shù)就是為處理這類需求而創(chuàng)建的。

對集合進(jìn)行分組
你是否嘗試過將一個(gè)集合按一定的規(guī)則拆分成兩個(gè)新的集合?比如,我們把某個(gè)集合拆分成偶數(shù)集和奇數(shù)集,partition 函數(shù)可以幫我們做到這一點(diǎn):

val numbers = Seq(3, 7, 2, 9, 6, 5, 1, 4, 2)

//(List(2, 6, 4, 2), List(3, 7, 9, 5, 1))

numbers.partition(n **=**> n **%** 2 **==** 0)

Fold
另一個(gè)流行的操作是fold。
在Scala 的上下文中,通常可以考慮 foldLeft 和 foldRight。他們是從不同的方面做同樣的工作:

val numbers = Seq(1, 2, 3, 4, 5)

//15

numbers.foldLeft(0)((res, n) **=**> res + n)

在第一對括號中,我們放一個(gè)起始值。
在第二對括號中,我們定義需要對數(shù)字序列的每個(gè)元素執(zhí)行的操作。
第一步,n = 0,然后它根據(jù)序列元素變化。
另一個(gè)關(guān)于foldLeft 的例子,計(jì)算字符數(shù):

val words = Seq("apple", "dog", "table")

//13

words.foldLeft(0)((resultLength, word) **=**> resultLength + word.length)

您最喜歡的函數(shù)
經(jīng)過了上面一系列的列舉,從Scala集合找到你最喜歡的函數(shù)是很酷的(cool)。請大家在評論中寫下它,并提供其使用的例子。

最近我通過了一個(gè)編譯測試,任務(wù)的內(nèi)容是:給你一個(gè)String S,你需要找到包含大寫和小寫字符,但不包含數(shù)字的最長子字符串。
比如: dP4knqw1QAp
答案: QAp
那么我們?nèi)绾问褂肧cala集合函數(shù)來解決這個(gè)問題呢:

def theLongest(s: String): String = {

  s.split ("[0-9]")

    .filter (_.exists (ch => ch.isUpper))

    .filter (_.exists (ch => ch.isLower))

    .maxBy (_.length)

}

上面的函數(shù)解決了這個(gè)問題。如果輸入字符串不包含任何合適的子字符串,將會拋出
UnsupportedOperationException。

總結(jié)
Scala具有令人難以置信的強(qiáng)大的集合API,你可以利用它做很多的事情。 此外,相同的事情可以以不同的方式進(jìn)行,例如: 上面的歐拉函數(shù)例子。 Scala的API是很豐富的,我們需要很多時(shí)間和練習(xí)來學(xué)習(xí)它。

參考:
10 amazing scala collection functions

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,928評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內(nèi)容