Kotlin: Как сгладить список хэшмапов - PullRequest
0 голосов
/ 12 февраля 2020

Как мне сгладить список HashMap s в Kotlin?

var listOfMaps: List<Map<String, String>> = listOf(mapOf("test" to "test1"), mapOf("test2" to "test3"), mapOf("test4" to "test5"))

Я бы хотел get:Map<String,String> со всеми парами значений ключа

Ответы [ 6 ]

1 голос
/ 12 февраля 2020

вы можете сделать что-то подобное, если не знаете, может ли список быть пустым.

val map = listOfMaps.fold(mapOf<String, String>()) {acc, value -> acc + value }

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

Спасибо, Полубог за комментарии

1 голос
/ 12 февраля 2020
val map:Map<String, String> = listOfMaps
    .flatMap { it.entries }
    .associate { it.key to it.value }
1 голос
/ 12 февраля 2020

Вы можете использовать fold:

listOfMaps.fold(
        mutableMapOf<String, String>(),
        { acc, item -> acc.also { it.putAll(item) } }
)

Первый параметр mutableMapOf<String, String>() создает пустую карту для помещения значений. Это называется аккумулятором

Второй параметр - это функция, которая принимает два аргумента

  1. Аккумулятор
  2. Элемент из исходного списка

Эта функция запускается последовательно для всех элементов в списке. В нашем случае он добавляет все элементы с каждой карты в аккумулятор.

Примечание. Эта функция не учитывает дубликаты ключей. Если более поздняя карта имеет тот же ключ, что и предыдущая, то значение просто переопределяется.

Также обратите внимание (каламбур предназначен): мы используем acc.also {}, поскольку мы хотим вернуть фактическую карту, а не возвращаемое значение из addAll метода

0 голосов
/ 12 февраля 2020

Что ж ... увидев множество решений, я добавлю два своих цента здесь:

Если вы не возражаете против потери значений дублированных ключей, вы можете использовать что-то следующее:

listOfMaps.flatMap { it.entries }.associate{ it.key to it.value } // or: it.toPair() if you will
// depending on how large those lists can become, you may want to consider also using asSequence

Если вместо этого вы хотите собрать все записи, включая дубликаты ключей (т.е. сохранить все значения), используйте вместо этого следующее (что затем дает Map<String, List<String>>):

listOfMaps.flatMap { it.entries }.groupBy({ it.key }) { it.value }

Также здесь комментарий относительно asSequence содержит ...

Наконец, если вы можете опустить эти карты в списке и просто использовать вместо него Pair, это избавит вас от вызова flatMap { it.entries } и сделает вещи еще проще, например, вы можете просто позвонить .toMap() тогда для первого случая и groupBy напрямую для второго, и вопрос о asSequence больше не возникает.

0 голосов
/ 12 февраля 2020

Если у вас нет дубликатов ключей или вы не заботитесь о них, вы можете сделать это следующим образом:

val flattenedMap = listOfMaps.flatMap { it.toList() }.toMap()

Если у вас есть дубликаты ключей и вы заботитесь о них, вы можете сделайте это так:

val flattenedMap = mutableMapOf<String, MutableList<String>>().apply {
    listOfMaps.flatMap { it.toList() }.forEach {
        getOrPut(it.first) {
            mutableListOf()
        }.add(it.second)
    }
}

Результат будет, конечно, Map<String, List<String>>.

0 голосов
/ 12 февраля 2020

Дополнительное дополнение к этому, если у вас есть карты с одним значением, возможно, вы захотите переключиться на List<Prair<String, String>>. В этом случае решение является простым:

Вы бы хотели что-то вроде:

var listOfMaps: List<Pair<String, String>> = listOf("test" to "test1", "test2" to "test3", "test4" to "test5")

, а toMap() все это решило бы:

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