Collect to map skipping null values
Since Kotlin 1.6, there is also a stable buildMap function that can be used to write custom helper functions that are performant without sacrificing readability:
fun <T, K : Any, V : Any> Iterable<T>.associateByNotNull(
keySelector: (T) -> K?,
valueTransform: (T) -> V?,
): Map<K, V> = buildMap {
for (item in this@associateByNotNull) {
val key = keySelector(item) ?: continue
val value = valueTransform(item) ?: continue
this[key] = value
}
}
Note that writing this as a "low-level" for loop eliminates the need for the creation of intermediate collections.
Actually, a slight change to pwolaq's answer guarantees that the second item is non-nullable:
val map = listOf(Pair("a", 1), Pair("b", null), Pair("c", 3), Pair("d", null))
.mapNotNull { p -> p.second?.let { Pair(p.first, it) } }
.toMap()
println(map)
This will give you a Map<String, Int>
, since mapNotNull
ignores anything that maps to null
, and using let
with the safe call operator ?.
returns null if its receiver (p.second
) is null
.
This is basically what you stated in your question, made shorter with let
.
You want to filter out null
values, then you should use filter
method:
val map = listOf(Pair("a", 1), Pair("b", null), Pair("c", 3), Pair("d", null))
.filter { it.second != null }
.toMap()
println(map)