filtering 對於集合來說是一個常見且常用的功能,在 lambda 內定義好 predicate(謂詞) 就會回傳一個 boolean 值,true 代表符合條件,false 代表不符合條件,篩選完畢後會回傳符合條件的集合。
說明
Filtering by predicate
如果你過濾的是 list 或 set,那麼結果就會輸出 list,如果你過濾的是 map 那麼結果就會輸出 map。
val numbers = listOf("one", "two", "three", "four")
val longerThan3 = numbers.filter { it.length > 3 }
println(longerThan3)
val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11)
val filteredMap = numbersMap.filter { (key, value) -> key.endsWith("1") && value > 10}
println(filteredMap)
結果如下。
[three, four]
{key11=11}
如果你要取得 index,你可以使用 filterIndexed,如果你要拿篩選後反向的元素,則可以使用 filterNot 。
val numbers = listOf("one", "two", "three", "four")
val filteredIdx = numbers.filterIndexed { index, s -> (index != 0) && (s.length < 5) }
val filteredNot = numbers.filterNot { it.length <= 3 }
println(filteredIdx)
println(filteredNot)
結果如下。
[two, four]
[three, four]
如果你的集合內有各種型態的元素,可以透過 filterIsInstance 來撈出集合內符合 TYPE 的元素。
val numbers = listOf(null, 1, "two", 3.0, "four")
println("All String elements in upper case:")
numbers.filterIsInstance<String>().forEach {
println(it.toUpperCase())
}
結果如下。
All String elements in upper case:
TWO
FOUR
如果你的集合內有 null 的元素,可以透過 filterNotNull 這個方法過濾掉。
val numbers = listOf(null, "one", "two", null)
numbers.filterNotNull().forEach {
println(it.length) // length is unavailable for nullable Strings
}
結果如下。
3
3
Partitioning
partition 顧名思義就是劃分,劃分成符合條件跟不符合條件了兩個部分,所以回來會有兩個集合。
val numbers = listOf("one", "two", "three", "four")
val (match, rest) = numbers.partition { it.length > 3 }
println(match)
println(rest)
結果如下。
[three, four]
[one, two]
Testing predicates
測試性的謂詞。
-
all()
: 全部條件必須成立,才會回傳 true。
val numbers = listOf("one", "two", "three", "four")
println(numbers.any { it.endsWith("e") })
println(numbers.none { it.endsWith("a") })
println(numbers.all { it.endsWith("e") })
println(emptyList<Int>().all { it > 5 }) // vacuous truth
最後一個 vacuous truth 是怎麼一回事,查一下 wiki,
在數理邏輯中,空虛的真是一種有條件的或普遍的陳述,只有在無法滿足前提條件時才成立。例如,無論何時房間中沒有手機,“房間中的所有手機都已關閉”的語句將為true。
也就是說當集合內沒有元素可以判斷的情況,無論條件是什麼都為真。
所以結果如下。
true
true
false
true
any() 跟 none() 都可以不用 predicate,
當 any() 沒有 predicate 的時候,只要集合有元素,則會回傳 true。
當 none() 沒有 predicate 的時候,只要集合有元素,則會回傳 false。
val numbers = listOf("one", "two", "three", "four")
val empty = emptyList<String>()
println(numbers.any())
println(empty.any())
println(numbers.none())
println(empty.none())
結果如下。
true
false
false
true