iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0

在整理資料的時候,分組也是一個很常見的需求,比方說 Collection 裡有很多字串,你想要依照字首的字母做分類,這樣的需求 Kotlin 的標準函式庫也都準備好啦!在這個章節裡就要跟大家介紹這方面的功能。

依條件群組

Kotlin 標準函式庫裡有 groupBy() method 可以用來做分組,我們需要傳入一個 Lambda 做分組條件,groupBy() 會回傳一個 Map。這個 Map 的 key 會是這個 Lambda 的結果,而對應的 value 就會是原始 Collection 裡的被分組的元素。

val numbers = listOf("one", "two", "three", "four", "five")
numbers.groupBy { it.first().toUpperCase() }
// {O=[one], T=[two, three], F=[four, five]}

分組後再做轉型

有時分組後,還會想要將裡面的元素轉型(Transform),與其要自己分兩步驟做,Kotlin 標準函式庫在設計 groupBy() 就想到這個需求了!所以 groupBy() 可以傳入 2 個 Lambda,第一個 Lambda 叫 keySelector,意思就是用什麼當做 key 的分組條件;第二個 Lambda 叫 valueTransform,意思就是要在 value 執行什麼轉換,兩個 Lambda 一併使用可以省下很多動作!

比方說剛剛上一個例子,我們除了用字首做分組外,還希望每一組裡面的字都可以字首大寫的話,我們可以這樣寫:

val numbers = listOf("oNe", "tWo", "tHRee", "foUR", "fIvE")

numbers.groupBy(
    keySelector = { it.first() },
    valueTransform = { it.toLowerCase().capitalize() }
)
// {O=[One], T=[Two, Three], F=[Four, Five]} 

分組後再做操作

有時分組後,還會想要再對各組的 Collection 做二次操作,比方說計算各組裡面的數量,這時可以使用的是 groupingBy(),它會回傳一個 Grouping 的類別,讓我們可以再套用如 eachCount()fold()reduce()aggregate() 等操作。換句話說,這個二次操作有可能會再次改變回傳 Map 裡 value 的格式與內容,讓分組動作可以做的事情更多!

val numbers = listOf("one", "two", "three", "four", "five", "six")
numbers.groupingBy { it.first() }.eachCount() // {o=1, t=2, f=2, s=1}

關於 fold()reduce()aggregate() 等轉型操作,我們會在後續的章節做更深入的討論。

表格整理

在這個章節裡,我們討論了 Collection 的分組,跟其他操作的不同之處,就是回傳的類型是 Map 而不是 List,這點要稍為注意一下。為了一覽這些 API 在不同 Collection 上的行為,以下用表格來整理本章所討論到的 method:

行為 Array List Set Map
groupBy{} 用 Lambda 分組 v v v x
groupingBy{}} 用 Lambda 分組後再操作 v v v x

參考資料


上一篇
第十七天:Collection 操作之搜尋
下一篇
第十九天:Collection 操作之迴圈
系列文
新手也能懂的 Kotlin Collection 賞玩門道31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言