La Función associateBy En Kotlin

ANUNCIO
Loading...

En este tutorial estudiarás el uso de la función associateBy en Kotlin para crear un mapa a partir de una colección, asignando la clave que resulte de una función de selección.

Sintaxis De associateBy

La función associateBy hace parte de las operaciones de asociación, las cuales tienen como fin generar mapas a partir de colecciones de elementos.

Su propósito es crear un mapa con pares cuyas claves sean generadas por una función pasada como parámetro llamada keySelector. Los valores del par serán los elementos de la colección. Si dos o más comparten la misma clave, solo se añadirá el último de todos ellos.

Ejemplo de la función associateBy En Kotlin

En el ejemplo anterior la función selectora { x < 0} produce dos claves posibles: true para los elementos menores a cero y false para cero y los positivos.

Como ves, aunque -2 y -1 se asocian a la clave false, tan solo se añade -1 ya que es el último elemento leído. De forma similar sucede con la clave true, solo 1 es añadido a la entrada. En Kotlin podemos materializar la asociación así:

fun main() { val numbers = listOf(-2, -1, 0, 1) println(numbers.associateBy { it < 0 }) // {true=-1, false=1} }
Lenguaje del código: Kotlin (kotlin)

La siguiente es la sintaxis de la función de extensión associateBy{ } para diferentes tipos:

// Arreglos inline fun <T, K> Array<out T>.associateBy( keySelector: (T) -> K ): Map<K, T> // Iterables inline fun <T, K> Iterable<T>.associateBy( keySelector: (T) -> K ): Map<K, T> // Strings inline fun <K> CharSequence.associateBy( keySelector: (Char) -> K ): Map<K, Char>
Lenguaje del código: Kotlin (kotlin)

Y los siguiente son diferentes configuraciones de keySelector para crear diferentes claves de tipo K.

fun main() { val numbers = listOf(-2, -1, 0, 1) println(numbers.associateBy { 1 }) // {1=1} val temperatures = floatArrayOf(32.1f, 40.5f, 30f, 30f, 14f) println(temperatures.associateBy { it }) // {32.1=32.1, 40.5=40.5, 30.0=30.0, 14.0=14.0} println("Develou.com".associateBy { it.toByte() }) // {68=D, 101=e, 118=v, 108=l, 111=o, 117=u, 46=., 99=c, 109=m} }
Lenguaje del código: Kotlin (kotlin)

El código anterior muestra como el valor 30f de temperatures y los caracteres 'e' y 'o' de "Develou.com" fueron omitidos por associateBy para asegurar la inclusión del último valor adecuado.

Y al usar el literal constante 1 como función de selección de clave, los tres primeros elementos de numbers fueron omitidos y solo se añadió 1 para el par resultante.

En definitiva, si buscas crear un mapa cuyos valores sean únicos y no te afecte el descarte de elementos de la colección inicial, usar associateBy te será de gran ayuda.

Ejemplo De La Función associateBy

Considera el escenario de modelado para la clase de datos que representa las cartas de un videojuego.

data class Card(val name: String, val cost: Int)
Lenguaje del código: Kotlin (kotlin)

Ahora supón que el jugador tiene en su mano varias cartas y debido a un efecto en el juego se desea conservar un ejemplar de cada costo y descartar el resto. Si hay costos repetidos se debe conservar la carta de más a la derecha.

fun main() { val hand = listOf( Card("Primer día de escuela", 0), Card("Humildad", 1), Card("Micromomia", 2), Card("Justicia de la luz", 1), Card("Protector argenta", 2) ) hand.associateBy { it.cost } .forEach { (cost, card) -> println("$cost: $card") } }
Lenguaje del código: Kotlin (kotlin)

Salida:

0: Card(name=Primer día de escuela, cost=0) 1: Card(name=Justicia de la luz, cost=1) 2: Card(name=Protector argenta, cost=2)
Lenguaje del código: HTTP (http)

El resultado de la asociación es el mapa sin las cartas "Humildad" y "Micromomia" como esperábamos.

Recuerda que la función lambda de antes puedes reescribirla con la referencia del miembro cost:

hand.associateBy(Card::cost)
Lenguaje del código: Kotlin (kotlin)

Usar associateBy Con Transformación

La función associateBy tiene una segunda forma para recibir una función que transforme los valores que será incluidos en los pares del mapa final.

Por ejemplo, si en el ejemplo anterior no quisiéramos tener valores del tipo Card, si no que solo necesitáramos los Strings de sus nombres, entonces pasamos una función para expresar esta mapeado:

fun main() { val hand = listOf( Card("Primer día de escuela", 0), Card("Humildad", 1), Card("Micromomia", 2), Card("Justicia de la luz", 1), Card("Protector argenta", 2) ) // associateBy con transform println(hand.associateBy({ it.cost }, { it.name })) }
Lenguaje del código: Kotlin (kotlin)

Salida:

{0=Primer día de escuela, 1=Justicia de la luz, 2=Protector argenta}

Aplicando esta variante podrás incluir el mapeado en una sola operación sin tener que incluir otro proceso de formato. Obviamente también es posible usar las referencias de los miembros si tu transformación es simple:

println(hand.associateBy(Card::cost, Card::name))
Lenguaje del código: Kotlin (kotlin)

¿Ha sido útil esta publicación?

ANUNCIO
Loading...