Как создать карту со значениями по умолчанию, если ключа нет?

#arrays #dictionary #kotlin

#массивы #словарь #kotlin

Вопрос:

Я хочу создать карту массива, анализирующую список объектов. Когда индекс этой карты уже добавлен, мне нужно добавить элементы массива, которые не были добавлены ранее, иначе мне нужно создать новый элемент на карте.

Допустим, у нас есть csv с такими данными

 names,nicknames
Tom,tommy;timmy
Sam,sammy
Tom,timmy;mymen
  

И я хочу такую карту :

 Map["Tom"] = ["tommy", "timmy", "mymen"]
Map["Sam"] = ["sammy"]
  

Я очень удивлен, что для этого нет встроенной функции

Что работает, но должно быть улучшено? (у меня есть 400 тыс. строк CSV для анализа)

     val myObjectList: List<myObject> = beans.parse() /* importing POJOs from csv*/
    val myMap: MutableMap<String,List<String>> = mutableMapOf()

    myObjectList.forEach { entry ->
       if ( myMap[entry.name].isNullOrEmpty()) {
           myMap[entry.name] = entry.nicknames.split(";")
       } else {
           myMap[entry.name]!!.plus(entry.nicknames.split(";"))
       }
    }


    return myMap
  

Комментарии:

1. Встроенной поддержки нет, я не думаю, что она будет. discuss.kotlinlang.org/t/… Разве вы не можете использовать guava MultiMap ?

2. MutliMap кажется именно тем, что мне нужно, но я избегаю добавлять зависимости в свой проект, когда это не жизненно важно. Я буду придерживаться своей плохой реализации 🙂 В любом случае спасибо за ваш ответ!

3. Я записал ответ, но я просто хотел уточнить, что проблема, которую вы хотите решить, заключается в том, «Как создать карту со значениями по умолчанию, если ключа нет?», А не способ эффективного чтения 400-строчного csv?

Ответ №1:

Используйте getOrPut как:

 data class MyObject(
        val name: String,
        val nicknames: String
)

fun main() {
    val myObjectList = listOf(
            MyObject("primary", "secondary1;secondary2"),
            MyObject("primary", "secondary3")
    )
    val nameToNicks = mutableMapOf<String, MutableList<String>>()

    myObjectList.forEach { myObj ->
        nameToNicks.getOrPut(myObj.name, {mutableListOf()}) .addAll(myObj.nicknames.split(";"))
    }

    print(nameToNicks)
}
  

Комментарии:

1. Спасибо! Сделал трюк! Я не могу понять, как это работает, потому что в документации сказано, что если значение уже сохранено, то последующие вызовы не имеют никакого эффекта?

2. Да, так что он будет создавать значение по умолчанию только один раз, это то, что он пытается сказать, я думаю. Поэтому, если вы установите для него значение null, оно не будет работать.