Jak przekonwertować List do Map w Kotlin?

169

Na przykład mam listę ciągów takich jak:

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

i chcę przekonwertować go na mapę, w której ciągi są kluczami.

Wiem, że powinienem użyć tej .toMap()funkcji, ale nie wiem jak i nie widziałem żadnych przykładów.

LordScone
źródło

Odpowiedzi:

317

Masz dwie możliwości:

Pierwszą i najbardziej wydajną metodą jest użycie associateByfunkcji, która pobiera dwie lambdy do generowania klucza i wartości, a także wstawia do tworzenia mapy:

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

Drugim, mniej wydajnym, jest użycie standardowej mapfunkcji do stworzenia listy, Pairktórej można użyć toMapdo wygenerowania ostatecznej mapy:

val map = friends.map { it.facebookId to it.points }.toMap()
voddan
źródło
1
Dziękuję Ci. czy jest szybszy, ponieważ tworzy mapę i nie konwertuje listy par na mapę, jak w moim przykładzie?
LordScone
4
@lordScone Dokładnie, alokacja Pairinstancji może być bardzo kosztowna w przypadku dużych kolekcji
voddan
41

Od Listdo Mapzassociate funkcją

W Kotlin 1.3 Listma funkcję o nazwie associate. associateposiada następującą deklarację:

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

Zwraca Mapzawierające pary klucz-wartość dostarczone przez transformfunkcję zastosowaną do elementów danej kolekcji.

Stosowanie:

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}
}    

Od Listdo MapzassociateBy funkcją

U Kotlina Listma funkcję o nazwie associateBy. associateByposiada następującą deklarację:

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

Zwraca wartość Mapzawierającą wartości podane przez valueTransformi indeksowane przez keySelectorfunkcje zastosowane do elementów danej kolekcji.

Stosowanie:

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}
}
Imanou Petit
źródło
3
Jaka jest różnica między Associate i AssociateBy? Czy wolałabym użyć jednego nad drugim, widząc, że dają ten sam rezultat?
Waynesford
11
  • Konwertuj iterowalne elementy sekwencji na mapę w kotlin,
  • Associate vs AssociateBy vs Associate

* Odniesienie: Dokumentacja Kotlin

1- Associate (aby ustawić zarówno klucze, jak i wartości): Zbuduj mapę, która może ustawić kluczowe i wartościowe elementy:

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

Jeśli którakolwiek z dwóch par ma ten sam klucz, ostatnia zostanie dodana do mapy.

Zwrócona mapa zachowuje kolejność iteracji pozycji oryginalnej tablicy.

2- AssociateBy (wystarczy ustawić klucze przez obliczenia): Zbuduj mapę, na której możemy ustawić nowe klucze, analogiczne elementy zostaną ustawione dla wartości

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

3- AssociateWith (po prostu ustaw wartości przez obliczenia): Zbuduj mapę, na której możemy ustawić nowe wartości, analogiczne elementy zostaną ustawione dla kluczy

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

Przykład z porad Kotlin: wprowadź opis obrazu tutaj

Hamed Jaliliani
źródło
10

Możesz użyć associatedo tego zadania:

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

W tym przykładzie ciągi znaków z liststają się kluczami, a odpowiadające im długości (na przykład) stają się wartościami wewnątrz mapy.

s1m0nw1
źródło
7

Jeśli masz na liście duplikaty , których nie chcesz stracić, możesz to zrobić za pomocągroupBy .

W przeciwnym razie, jak wszyscy mówili, użyj associate/By/With(co, jak sądzę, w przypadku duplikatów zwróci tylko ostatnią wartość z tym kluczem).

Przykład grupowania listy osób według wieku:

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)
}

Wyniki:

{31=[Person@41629346, Person@4eec7777], 25=[Person@3b07d329]}
{31=Person@4eec7777, 25=Person@3b07d329}
cs_pupil
źródło
0

To się zmieniło w wersji RC.

ja używam val map = list.groupByTo(destinationMap, {it.facebookId}, { it -> it.point })

Lagos
źródło