La Función map En Kotlin

En este tutorial verás cómo usar la función map en Kotlin para aplicar funciones que transformen a cada elemento de una colección.

La Función map()

La función de orden superior map{ } te permite aplicar una función sobre todos los elementos de una colección con el fin de una nueva colección con el cálculo final.

Por ejemplo, si tenemos la lista de enteros L = { -2, -1, 0, 1 } y quisiéramos obtener otra lista que tome cada elemento como argumento y aplique la función f(x) = 2x+1, la transformación final será:

La función map en Kotlin

Luego de aplicar la función sobre cada elemento entero, el resultado es la lista R = [-3, -1, 1, 3].

Sintaxis De map{ }

Ya que map{ } debe aplicarse a varios tipos de colecciones, su sintaxis cambia para cada una de ellas, pero su naturelaza es la misma.

// Mapear Arreglos
inline fun <T, R> Array<out T>.map(
    transform: (T) -> R
): List<R>

// Mapear Iterables (listas, sets, strings, rangos, ...)
inline fun <T, R> Iterable<T>.map(
    transform: (T) -> R
): List<R>

// Mapear Mapas
inline fun <K, V, R> Map<out K, V>.map(
    transform: (Entry<K, V>) -> R
): List<R>

Todas las sintaxis coinciden en el mecanismo explicado anteriormente. Se usa como argumento un tipo función transform, donde el parámetro es el elemento de la colección y el cuerpo un bloque de código que termine en un resultado de tipo R.

Por ende el resultado es una lista parametrizada List<R> con los componentes ya transformados.

Usar map Con Listas

Considera la lista de estados L = [fácil, intermedio, difícil, pesadilla] y la necesidad de convertir cada String a mayúsculas. Haciendo uso de la función map tendrás:

fun main() {
    val difficultyLevels = listOf("fácil", "intermedio", "difícil", "pesadilla")
    println(difficultyLevels.map { it.toUpperCase() })
}

Salida:

[FÁCIL, INTERMEDIO, DIFÍCIL, PESADILLA]

La solución consistió en pasar una función lambda que invoque a la función de extensión String.toUpperCase() de cada elemento. El elemento es representado por la referencia it.

Veámos otro ejemplo.

Ahora supongamos que tenemos una clase de datos que representa sitios turísticos llamada TouristicPlace:

data class TouristicPlace(val name: String, val country: String)

Si quisieras obtener una lista con solo los nombres de una colección de varios sitios turísticos, entonces es posible usar un mapeado donde el cuerpo de la lambda sea el acceso a la propiedad name.

fun main() {
    val places = listOf(
        TouristicPlace("Torre Eiffel", "Francia"),
        TouristicPlace("Coliseo Romano", "Italia"),
        TouristicPlace("Acropolis de Atenas", "Grecia"),
        TouristicPlace("Taj Mahal", "India")
    )

    println(places.map { it.name })
}

Salida:

[Torre Eiffel, Coliseo Romano, Acropolis de Atenas, Taj Mahal]

Usar map Con Mapas

Recuerda que la sintaxis para aplicar la función map en mapas usa como parámetro cada entrada Entry<K, V>, por lo que puedes acceder a cada componente en tu transformación.

Por ejemplo, se crea un mapa para guardar el puntaje de varios jugadores a través de los pares de su nombre y puntaje. Se requiere mapear en una vista de lista la conjugación de cada entrada para que explique el puntaje obtenido:

fun main() {
    val playersAndScore = mapOf(
        "José" to 10,
        "Brenda" to 5,
        "Karina" to 11,
        "Ricardo" to 7
    )

    val listView = playersAndScore.map { "${it.key} obtuvo ${it.value} puntos" }
    listView.forEach { println(it) }
}

Salida:

José obtuvo 10 puntos
Brenda obtuvo 5 puntos
Karina obtuvo 11 puntos
Ricardo obtuvo 7 puntos

Crear el mensaje para cada elemento consistió de acceder a las propiedades key y value a través de la referencia it en la lambda.

Mapear Claves

La librería estándar te provee funciones para transformar a las claves y valores por separado.

Usa mapKeys() para obtener un nuevo mapa cuyas claves serán las que especifiques en función de transformación. Los valores serán los mismos del mapa original:

println(playersAndScore.mapKeys {
    it.key
        .take(3)
        .toUpperCase()
})// {JOS=10, BRE=5, KAR=11, RIC=7}

El ejemplo anterior genera una clave que corresponde a la versión de los tres primeros caracteres en mayúscula.

Mapear Valores

Para el caso de mapeado de valores, usa la función mapValues(). Retorna un nuevo mapa con las claves del mapa de origen y sus valores serán el resultado de la función de transformación:

println(playersAndScore.mapValues { it.value * 10})
// {José=100, Brenda=50, Karina=110, Ricardo=70}

El código anterior multiplica la puntuación por 10. De esta forma las claves de origen se mantienen y los valores cambian al producto esperado.

Únete Al Discord De Develou

Si tienes problemas con el código de este tutorial, preguntas, recomendaciones o solo deseas discutir sobre desarrollo Android conmigo y otros desarrolladores, únete a la comunidad de Discord de Develou y siéntete libre de participar como gustes. ¡Te espero!