Como converter lista em mapa no Kotlin?

169

Por exemplo, eu tenho uma lista de strings como:

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

e eu quero convertê-lo em um mapa, onde as strings são as chaves.

Eu sei que devo usar a .toMap()função, mas não sei como e não vi nenhum exemplo disso.

LordScone
fonte

Respostas:

316

Você tem duas opções:

O primeiro e mais associateByeficiente é usar a função que usa duas lambdas para gerar a chave e o valor e destaca a criação do mapa:

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

O segundo, com menos desempenho, é usar a mapfunção padrão para criar uma lista da Pairqual pode ser usada toMappara gerar o mapa final:

val map = friends.map { it.facebookId to it.points }.toMap()
voddan
fonte
1
obrigado. é mais rápido porque cria um mapa e não converte uma lista de pares em um mapa, como no meu exemplo?
LordScone
4
@lordScone Exatamente, as alocações de Paircasos pode ser muito caro para grandes coleções
voddan
40

De Listpara Mapcom associatefunção

Com o Kotlin 1.3, Listtem uma função chamada associate. associatetem a seguinte declaração:

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

Retorna um Mappar de valores-chave contendo a transformfunção aplicada aos elementos da coleção fornecida.

Uso:

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

De Listpara Mapcom associateByfunção

Com Kotlin, Listtem uma função chamada associateBy. associateBytem a seguinte declaração:

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

Retorna a Mapcontendo os valores fornecidos valueTransforme indexados por keySelectorfunções aplicadas aos elementos da coleção fornecida.

Uso:

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
fonte
3
Qual a diferença entre associar e associarBy? Gostaria de preferir usar um sobre o outro, visto que eles produzem o mesmo resultado?
waynesford
11
  • Converta elementos de sequência iteráveis ​​em um mapa no kotlin,
  • associar vs associarBy vs associar com:

* Referência: Documentação Kotlin

1- associar (para definir chaves e valores): Construa um mapa que possa definir elementos de chave e valor:

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

Se qualquer um dos dois pares tiver a mesma chave, o último será adicionado ao mapa.

O mapa retornado preserva a ordem de iteração de entrada da matriz original.

2- associarBy (basta definir chaves por cálculo): Construa um mapa para definir novas chaves, elementos análogos serão definidos para valores

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

3- associarCom (apenas definir valores por cálculo): Construir um mapa que possamos definir novos valores, elementos análogos serão definidos para chaves

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

Exemplo das dicas do Kotlin: insira a descrição da imagem aqui

Hamed Jaliliani
fonte
9

Você pode usar associatepara esta tarefa:

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

Neste exemplo, as seqüências de caracteres listtornam - se as chaves e seus comprimentos correspondentes (como exemplo) tornam-se os valores dentro do mapa.

s1m0nw1
fonte
7

Se houver duplicatas em sua lista que não deseja perder, faça isso usandogroupBy .

Caso contrário, como todo mundo disse, use associate/By/With(que, no caso de duplicatas, acredito, retornará apenas o último valor com essa chave).

Um exemplo de agrupamento de uma lista de pessoas por idade:

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

Resultados:

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

Isso mudou na versão RC.

estou usando val map = list.groupByTo(destinationMap, {it.facebookId}, { it -> it.point })

lagos
fonte