Reputation: 12177
I have the following data-structure:
var foo: Map<String, List<String>> = emptyMap()
foo += mapOf(
"1" to listOf("a", "b"),
"2" to listOf("a", "b"),
"3" to listOf("a", "b")
)
Map and sub-list are both immutable. I now want to add the element c
to the list of the first element in the map.
I came up with this solutions:
foo += "1" to (foo["1"] ?: emptyList()) + "c"
but is this really the idiomatic way?
Update based on @hotkeys answer
foo += "1" to foo["1"].orEmpty() + "c"
Upvotes: 2
Views: 74
Reputation: 1505
The declaration and assignment can be joined unless there is some problem. Make map & list mutable, as the need is to mutate
var foo: MutableMap<String, MutableList<String>> = mutableMapOf(
"1" to mutableListOf("a", "b"),
"2" to mutableListOf("a", "b"),
"3" to mutableListOf("a", "b")
)
we can use when block like below,
when {
foo.containsKey("1") -> foo["1"]?.add("c")
else -> foo["1"] = mutableListOf("c")
}
Upvotes: 0
Reputation: 148001
One alternative you could check is the approach that the incubating library kotlinx.collections.immutable
uses (or just use that library). It allows you to .mutate { ... }
a map, which creates an immutable copy of that map with the applied mutations:
val m = immutableHashMapOf("1" to listOf("a", "b"))
val result = m.mutate { it["1"] = it["1"].orEmpty() + "c" }
See also: .orEmpty()
There's no equivalent to .mutate { ... }
in the standard library, though, but you can define your own extension for read-only Map
that would do the same.
Upvotes: 1