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á:
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.