篩選集合
篩選是集合處理中最常見的任務之一。 在 Kotlin 中,篩選條件由_謂詞_定義 – 謂詞是接受集合元素並回傳布林值 (boolean value) 的 Lambda 函式:true
表示給定元素符合該謂詞,false
表示相反。
標準函式庫包含一組擴充函式,讓您可以單次呼叫即可篩選集合。 這些函式不會改變原始集合,因此它們適用於可變與唯讀集合。若要操作篩選結果,您應該將其賦值給變數或在篩選後鏈接函式。
按謂詞篩選
基本篩選函式是 filter()
。 當使用謂詞呼叫時,filter()
會回傳符合該謂詞的集合元素。 對於 List
和 Set
,結果集合是 List
;對於 Map
,它也是 Map
。
fun main() {
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)
}
filter()
中的謂詞只能檢查元素的數值。 如果您想在篩選中使用元素位置,請使用 filterIndexed()
。 它接受一個具有兩個引數的謂詞:元素的索引和值。
若要按負面條件篩選集合,請使用 filterNot()
。 它會回傳謂詞結果為 false
的元素列表。
fun main() {
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)
}
還有一些函式透過篩選給定型別的元素來縮小元素型別:
filterIsInstance()
會回傳給定型別的集合元素。在List<Any>
上呼叫時,filterIsInstance<T>()
會回傳List<T>
,因此允許您在其項目上呼叫T
型別的函式。kotlinfun main() { val numbers = listOf(null, 1, "two", 3.0, "four") println("所有 String 元素均為大寫:") numbers.filterIsInstance<String>().forEach { println(it.uppercase()) } }
filterNotNull()
會回傳所有非空元素。在List<T?>
上呼叫時,filterNotNull()
會回傳List<T: Any>
,因此允許您將這些元素視為非空物件。kotlinfun main() { val numbers = listOf(null, "one", "two", null) numbers.filterNotNull().forEach { println(it.length) // length 對於可空 Strings 不可用 } }
分區
另一個篩選函式 – partition()
– 會按謂詞篩選集合,並將不符合該謂詞的元素保留在單獨的列表中。 因此,您會得到一個 List
型別的 Pair
作為回傳值:第一個列表包含符合謂詞的元素,第二個列表包含來自原始集合的所有其他元素。
fun main() {
val numbers = listOf("one", "two", "three", "four")
val (match, rest) = numbers.partition { it.length > 3 }
println(match)
println(rest)
}
測試謂詞
最後,還有一些函式只是針對集合元素測試謂詞:
any()
如果至少一個元素符合給定謂詞,則回傳true
。none()
如果沒有元素符合給定謂詞,則回傳true
。all()
如果所有元素都符合給定謂詞,則回傳true
。 請注意,all()
在空集合上使用任何有效謂詞呼叫時都會回傳true
。這種行為在邏輯中被稱為_空泛真理_。
fun main() {
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 }) // 空泛真理
}
any()
和 none()
也可以在沒有謂詞的情況下使用:在這種情況下,它們僅檢查集合是否為空。 any()
如果存在元素則回傳 true
,否則回傳 false
;none()
則執行相反操作。
fun main() {
val numbers = listOf("one", "two", "three", "four")
val empty = emptyList<String>()
println(numbers.any())
println(empty.any())
println(numbers.none())
println(empty.none())
}