Translate

domingo, 23 de diciembre de 2018

Operaciones comunes con collections en Kotlin


Vamos a revisar el conjunto de funciones que tiene kotlin para manejo de colecciones:

Vamos a empezar con 'filter'. Éste filtra el contenido de la lista y mantiene solo los elementos que satisfacen el predicado. Por ejemplo, aquí tenemos el predicado que comprueba que un número es par, y solo los números pares están presentes en la lista resultante.

val originalList = listOf(1, 2, 3, 4, 5, 6)
assertEquals(listOf(2, 4, 6), originalList.filter { it % 2 == 0 })

La función map() transforma una colección en una nueva, y transforma cada elemento en esta colección. Por ejemplo, aquí encontramos un cuadrado de cada número dado y la colección resultante es una colección de cuadrados. Tenga en cuenta que la colección resultante contiene tantos elementos como el primero.

 val nums = listOf(1, 2, 3, 4, 5, 6)
 val nums2 = nums.map { e -> e * 2 }
 println(nums2)

Hay varios predicados que verifican si los hechos dados son verdaderos para los elementos. Por ejemplo, 'any' comprueba que hay al menos un elemento que satisface el predicado dado. all verifica si todos los elementos satisfacen el predicado, y none comprueba que ninguno de los elementos satisface el predicado dado.

 val nums = listOf(4, 5, 3, 2, -1, 7, 6, 8, 9)
 val r = nums.any { e -> e > 10 }
 if (r) println("There is a value greater than ten")
    else println("There is no value greater than ten")

r = nums.all { e -> e > 0 }
if (r) println("nums list contains only positive values")
    else println("nums list does not contain only positive values")

r = nums.none { e -> e > 0 }
if (!r) println("nums list contains only positive values")
    else println("nums list does not contain only positive values")

find() encuentra un elemento que satisface el predicado dado y lo devuelve como resultado. Si no hay ningún elemento (obligatorio) que devuelve null.

firstOrNull() busca el primer elemento te devuelve un elemento o 'null' como resultado. Mientras que first() solo toma un predicado y lanza una excepción si no hay tal elemento

val originalList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = originalList.firstOrNull { it > 4 }
assertEquals(result, 5)

count() cuenta el número de elementos que satisfacen el predicado dado. max retorna el máximo, min el mínimo:

val nums = listOf(11, 5, 3, 8, 1, 9, 6, 2)
val len = nums.count()
val max = nums.max()
val min = nums.min()
val msg = """
               max: $max, min: $min,
               count: $len
              """
println(msg.trimIndent())

partition divide la colección en dos (colecciones) los que cumplen o no un predicado.

val nums = listOf(4, -5, 3, 2, -1, 7, -6, 8, 9)

val (nums2, nums3) = nums.partition { e -> e < 0 }
println(nums2)
println(nums3)

Si desea dividir la colección en varios grupos por clave dada, puede usar groupBy utilizando como argumento la forma de agrupar los elementos, cuál debería ser la clave. Por ejemplo

val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8)
val res = nums.groupBy { if (it % 2 == 0) "even" else "odd" }
println(res)

AssociateBy también realiza la agrupación, pero devuelve un elemento como el valor del mapa. AssociateBy debe usarse solo si la clave es única. Si no es así, se eliminan los duplicados. De esta forma nos quedamos con el ultimo.

val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8)
nums.associate { (if (it % 2 == 0) "greatest_even" else "greatest_odd") to it }

Otra forma de organizar de alguna manera un par de colecciones es zip. El cual las une :

val names = listOf("Jon", "John", "Jane")
val ages = listOf(23, 32, 28)

names.zip(ages)
// [(Jon, 23), (John, 32), (Jane, 28)]

Otra función útil es flatMap. Esta consta de dos operaciones, la primera es map y la segunda es flatten. map en este caso debería convertir cada elemento a una lista de elementos. y el flatten aplana las listas resultantes :

val customerMap = mapOf(Pair(Customer("Jack", 25), Address("NANTERRE CT", "77471")),
Pair(Customer("Mary", 37), Address("W NORMA ST", "77009")),
Pair(Customer("Peter", 18), Address("S NUGENT AVE", "77571")),
Pair(Customer("Amos", 23), Address("E NAVAHO TRL", "77449")),
Pair(Customer("Craig", 45), Address("AVE N", "77587")))

val customerList = customerMap.flatMap { (customer, _) -> listOf(customer) }
customerList.forEach{ println(it) }
/*
Customer(name=Jack, age=25)
Customer(name=Mary, age=37)
Customer(name=Peter, age=18)
Customer(name=Amos, age=23)
Customer(name=Craig, age=45)
*/

Y a veces tenemos una lista de solo elementos como resultado. Entonces, lo que hace la función flatten, toma una lista de listas de elementos y la aplana retorna una lista plana

val list = listOf(
listOf(1, 2, 3),
listOf("one", "two", "three"),
listOf(Customer("Jack", 25), Customer("Peter", 31), Customer("Mary", 18))
)

var flattenList = list.flatten()

println(flattenList)
/*
[1, 2, 3, one, two, three, Customer(name=Jack, age=25), Customer(name=Peter, age=31), Customer(name=Mary, age=18)]
*/

Dejo link: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/