Як перетворити список на карту в Котліні?


169

Наприклад, у мене є список рядків типу:

val list = listOf("a", "b", "c", "d")

і я хочу перетворити його на карту, де рядки є ключами.

Я знаю, що я повинен використовувати цю .toMap()функцію, але не знаю як, і я не бачив жодних прикладів цього.

Відповіді:


317

У вас є два варіанти:

Перше і найефективніше - це використовувати associateByфункцію, яка займає два лямбда для генерації ключа і значення, а також накреслює створення карти:

val map = friends.associateBy({it.facebookId}, {it.points})

Друга, менш ефективна, полягає у використанні стандартної mapфункції для створення списку, за допомогою Pairякого можна toMapсформувати остаточну карту:

val map = friends.map { it.facebookId to it.points }.toMap()

1
спасибі. це швидше, тому що створює карту, а не перетворює список пар на карту, як у моєму прикладі?
LordScone

4
@lordScone Точно розподіл Pairекземплярів може бути дуже дорогим для великих колекцій
voddan

41

З Listдо Mapз associateфункцією

З Kotlin 1.3, Listмає функцію під назвою associate. associateмає таку заяву:

fun <T, K, V> Iterable<T>.associate(transform: (T) -> Pair<K, V>): Map<K, V>

Повертає Mapмістять пари ключ-значення, надані transformфункцією, застосованою до елементів даної колекції.

Використання:

class Person(val name: String, val id: Int)

fun main() {
    val friends = listOf(Person("Sue Helen", 1), Person("JR", 2), Person("Pamela", 3))
    val map = friends.associate({ Pair(it.id, it.name) })
    //val map = friends.associate({ it.id to it.name }) // also works

    println(map) // prints: {1=Sue Helen, 2=JR, 3=Pamela}
}    

З Listдо Mapз associateByфункцією

У Котліна Listє функція під назвою associateBy. associateByмає таку заяву:

fun <T, K, V> Iterable<T>.associateBy(keySelector: (T) -> K, valueTransform: (T) -> V): Map<K, V>

Повертає Mapвміст, що містить значення, надані valueTransformта індексовані keySelectorфункціями, застосованими до елементів даної колекції.

Використання:

class Person(val name: String, val id: Int)

fun main() {
    val friends = listOf(Person("Sue Helen", 1), Person("JR", 2), Person("Pamela", 3))
    val map = friends.associateBy(keySelector = { person -> person.id }, valueTransform = { person -> person.name })
    //val map = friends.associateBy({ it.id }, { it.name }) // also works

    println(map) // prints: {1=Sue Helen, 2=JR, 3=Pamela}
}

3
Яка різниця між асоційованим та асоційованимBy? Чи хотів би я вважати за краще використовувати один над іншим, бачачи, що вони дають однаковий результат?
Уейнсфорд

11
  • Перетворіть елементи, які можна відмінити, на карту в kotlin,
  • Associate vs AssociateBy vs associateWith:

* Довідка: Документація Котліна

1- асоційований (для встановлення і ключів, і значень): Створіть карту, в якій можна встановити елементи ключа та значення:

IterableSequenceElements.associate { newKey to newValue } //Output => Map {newKey : newValue ,...}

Якщо будь-яка з двох пар матиме однаковий ключ, до карти додається останній.

Повернута карта зберігає порядок ітерації входу вихідного масиву.

2- AssociateBy (просто встановіть Ключі за розрахунком): Створіть карту, яку ми можемо встановити нові Ключі, аналогічні елементи будуть встановлені для значень

IterableSequenceElements.associateBy { newKey } //Result: => Map {newKey : 'Values will be set  from analogous IterableSequenceElements' ,...}

3- AssociateWith (просто встановити Значення шляхом обчислення): Створіть карту, яку ми можемо встановити нові Значення, аналогічні елементи будуть встановлені для Ключів

IterableSequenceElements.associateWith { newValue }  //Result => Map { 'Keys will be set from analogous IterableSequenceElements' : newValue , ...}

Приклад з порад Котліна: введіть тут опис зображення


10

Ви можете використовувати associateдля цього завдання:

val list = listOf("a", "b", "c", "d")
val m: Map<String, Int> = list.associate { it to it.length }

У цьому прикладі рядки від listклавіш стають ключами та їх відповідні довжини (як приклад) стають значеннями всередині карти.


7

Якщо у вашому списку є дублікати, які ви не хочете втрачати, ви можете це зробити, використовуючи groupBy.

Інакше, як і всі інші сказали, використовуйте associate/By/With(що у випадку дублікатів, я вважаю, поверне останнє значення лише за допомогою цього ключа).

Приклад групування списку людей за віком:

class Person(val name: String, val age: Int)

fun main() {
    val people = listOf(Person("Sue Helen", 31), Person("JR", 25), Person("Pamela", 31))

    val duplicatesKept = people.groupBy { it.age }
    val duplicatesLost = people.associateBy({ it.age }, { it })

    println(duplicatesKept)
    println(duplicatesLost)
}

Результати:

{31=[Person@41629346, Person@4eec7777], 25=[Person@3b07d329]}
{31=Person@4eec7777, 25=Person@3b07d329}

0

Це змінилося у версії RC.

я використовую val map = list.groupByTo(destinationMap, {it.facebookId}, { it -> it.point })

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.