iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 15
0
Software Development

新手也能懂的 Kotlin Collection 賞玩門道系列 第 15

第十五天:Collection 操作之排序

在處理資料時,順序有時是重要的。比方說,我們想要將 Collection 裡的數字從小到大來排,或是想將 Collection 裡的名字從 a 到 z 排。在比較兩個 List 的時候,即便內容元素都相同,但順序不同也會被視為不同的 List,由此可見順序在資料處理的重要性。在這個章節裡,我們就要來看一下 Collection 可以有哪些排序 method 可以用?

排序

Kotlin 排序的功能很單純,要依照序列正排就用 sorted()、要反排就用 sortedDescending(),Kotlin 會自動依照自然排序(Natural Order)排列所有元素。所謂自然排序對數字(Numeric)類型來說就是照著數學觀念的大小來做排序,1 大於 0、-3 大於 -5;而對字元(Char)或字串(String)的話,則依 a-z 的順序來排,非常直覺。

val numbers = listOf("one", "two", "three", "four")

val sortedNumbers = numbers.sorted() // [four, one, three, two]
val sortedDescNumbers = numbers.sortedDescending() // [two, three, one, four]

自定排序

假如今天需要客製化排序的邏輯,或是放在 Collection 裡的元素沒有實作 Comparable 介面的話,那就需要用 sortedBy()sortedByDescending() 搭配 Lambda 來使用了。

val numbers = listOf("one", "two", "three", "four")

val sortedNumbers = numbers.sortedBy { it.length } // [one, two, four, three]
val sortedByLast = numbers.sortedByDescending { it.last() } // [four, two, one, three]

另一種自定排序的方式,就是用 sortedWith() 並傳入一個 Comparator 的介面,所以上面的例子可以改寫成:

val numbers = listOf("one", "two", "three", "four")
val sortedNumbers = numbers.sortedWith(compareBy { it.length }) // [one, two, four, three]

反轉排序

排序的重要之處就是在拿取元素的時候可以照順序拿,但有時需要依照原本的順序反著拿,這時最快的方式就是將排序反轉。在 Kotlin 你也不需要自己用迴圈來處理,只需要呼叫 reversed() 即可。

val numbers = listOf("one", "two", "three", "four")
val reversedNumbers = numbers.reversed() // 

基本上,所有排序的 method 都不會更動到原本的 Collection。也就是說,今天若 numbers 的內容更動了,reversedNumbers 並不會依照新的內容重新排序,這樣會有點不方便。若你希望可以產生出一個類似 View 的概念,Kotlin 也提供一個 asReversed() 的 method,它會自動同步每次的更新。

val numbers = mutableListOf("one", "two", "three", "four")
val reversedNumbers = numbers.asReversed() // 這時 reversedNumbers 是 [four, three, two, one]
numbers.add("five") // 這時 reversedNumbers 變成 [five, four, three, two, one]

隨機排序

跟一般的排序目的不同,有時為了創造隨機性,需要把 Collection 裡的排序故意弄亂。比方說,今天你要寫一個尾牙抽獎程式,Collection 就是抽獎箱,裡面裝著抽獎名單,每次抽獎前都要先把抽獎箱搖一搖以示公平,這時你就會需要隨機排序。在 Kotlin 裡要讓 Collection 裡的元素隨機排序很簡單,只要使用 shuffled() 就可以了。要注意的是,shuffled() 會回傳整個隨機排序過後的 Collection,跟前面章節裡隨機取出一個元素的 random() 在行為上是不一樣的喔!

val numbers = listOf("one", "two", "three", "four")
val shuffledNumbers = numbers.shuffled() // 每次出現的結果都會不同

表格整理

在這個章節裡,我們討論了幾個常用的排序方式。要提醒一下,這些排序方式大多數都不會影響到原本的 Collection,所以要保留結果的話,就要宣告一個新的變數來儲存,在資料操作時要特別注意這個特點。

為了一覽這些 API 在不同 Collection 上的行為,以下用表格來整理本章所討論到的 method:

行為 Array List Set Map
sorted() 自然排序 v v v x
sortedDescending() 反向自然排序 v v v x
sortedBy{} 自定排序 v v v x
sortedByDescending{} 反向自定排序 v v v x
sortedWith() 自定排序 v v v x
reversed() 反轉排序 v v v x
asReversed() 取得反轉排序 View x v x x
shuffled() 隨機排序 x v v x

參考資料


上一篇
第十四天:Collection 操作之過濾
下一篇
第十六天:Collection 操作之檢查
系列文
新手也能懂的 Kotlin Collection 賞玩門道31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言