Идиоматический способ добавить элемент в подсписок в полностью неизменной иерархии - PullRequest
0 голосов
/ 01 мая 2018

У меня есть следующая структура данных:

var foo: Map<String, List<String>> = emptyMap()
foo += mapOf(
        "1" to listOf("a", "b"),
        "2" to listOf("a", "b"),
        "3" to listOf("a", "b")
)

Карта и подсписок являются неизменяемыми. Теперь я хочу добавить элемент c в список первого элемента на карте.

Я придумал это решение:

foo += "1" to (foo["1"] ?: emptyList()) + "c"

но разве это идиоматический способ?


Обновление на основе ответа @hotkeys

foo += "1" to foo["1"].orEmpty() + "c"

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Объявление и присваивание могут быть объединены, если нет каких-либо проблем. Сделать карту и список изменяемыми, так как нужно мутировать

var foo: MutableMap<String, MutableList<String>> = mutableMapOf(
        "1" to mutableListOf("a", "b"),
        "2" to mutableListOf("a", "b"),
        "3" to mutableListOf("a", "b")
)

мы можем использовать , когда блок , как показано ниже,

when {
    foo.containsKey("1") -> foo["1"]?.add("c")
    else -> foo["1"] = mutableListOf("c")

}
0 голосов
/ 01 мая 2018

Одна альтернатива, которую вы можете проверить, - это подход, который использует инкубационная библиотека kotlinx.collections.immutable (или просто используйте эту библиотеку). Это позволяет вам .mutate { ... } карту, которая создает неизменную копию этой карты с примененными мутациями:

val m = immutableHashMapOf("1" to listOf("a", "b"))

val result = m.mutate { it["1"] = it["1"].orEmpty() + "c" }

См. Также: .orEmpty()

Хотя в стандартной библиотеке нет эквивалента .mutate { ... }, но вы можете определить свое собственное расширение только для чтения Map, которое будет делать то же самое.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...