En este tutorial aprenderás acerca del uso de la función partition
en Kotlin para dividir una colección en dos colecciones, una para los elementos que satisfacen un predicado y otra para los que no.
Uso De La Función partition()
La función de extensión partition()
hace parte de la categoría de operaciones para el filtrado de colecciones.
Su propósito es aplicar una función de predicado a una colección y retornar en dos colecciones, la primera para aquellos elementos que cumplieron la condición y la segunda para los que no la satisfacen.
La ilustración anterior toma como objetivo de la función partition()
a la lista L=[-2, -1, 0, 1, 2]
. El predicado pasado como parámetro es una función lambda con la condición de si los elementos son positivos.
Al aplicar la división de elementos el resultado será una instancia de Pair
, donde el primer elemento serán aquellos ítems que cumplen first = [1, 2]
y el segundo será la lista de los que no second=[-2, -1, 0]
.
Este ejemplo lo puedes escribir en Kotlin de la siguiente forma:
fun main() {
val numbers = listOf(-2, -1, 0, 1, 2) // 1
val isPositive = { number: Int -> number > 0 } // 2
println(numbers.partition(isPositive)) // 3
println(numbers.partition { it > 0 }) // 4
}
Salida:
([1, 2], [-2, -1, 0])
Como ves en la línea dos almacenamos al predicado en la variable isPositive
y en tres imprimimos el resultado de partition()
pasándola como parámetro. Sin embargo esto puede ser ejecutado en una sola línea con la referencia it
en cuatro si no requieres más contexto.
Sintaxis De partition()
La siguiente es la sintaxis de la función partition()
en varios tipos:
// partition() en arreglos
inline fun <T> Array<out T>.partition(
predicate: (T) -> Boolean
): Pair<List<T>, List<T>>
// partition() en iterables
inline fun <T> Iterable<T>.partition(
predicate: (T) -> Boolean
): Pair<List<T>, List<T>>
// partition() en Strings
inline fun String.partition(
predicate: (Char) -> Boolean
): Pair<String, String>
Recuerda que los predicados toman como parámetro el tipo del elemento de la colección y en su cuerpo deben existir sentencias que terminen en un valor final de tipo Boolean
.
Debido a que el retorno es de tipo Pair
, el resultado puede ser accedido a través de componentes de desestructuración.
Por ejemplo, si deseas separar en dos listas los caracteres de un String en aquellos que su código numérico sea mayor a 50 y en otra de los que no:
fun main() {
val text = "Procesando repartición..."
val greaterThan50 = { c: Char -> c.toByte() > 50 }
val (charsGT50, charsLT50) = text.partition(greaterThan50)
println("Mayores a 50: ${charsGT50.length}")
println("Menores a 50: ${charsLT50.length}")
}
Al aplicar partition()
es posible usar los componentes desesctructurados charsGT50
y charsLT50
para obtener la cantidad de caracteres en cada lista.
Otra forma de acceso al resultado es con las propiedades Pair.first
y Pair.second
:
fun main() {
val text = "Procesando repartición..."
val greaterThan50 = { c: Char -> c.toByte() > 50 }
val partitionResult = text.partition(greaterThan50)
println("Mayores a 50: ${partitionResult.first.length}")
println("Menores a 50: ${partitionResult.second.length}")
}
Ejemplo De partition() En Arreglo
Considera un arreglo de 10 palabras de las cuales se desea obtener un promedio de su cantidad de caracteres.
Específicamente, se requiere saber el promedio para aquellas que inician con vocales y para las que inician con consonantes.
Si aplicamos el uso de partition()
la siguiente es una de las soluciones posibles:
fun main() {
val words = arrayOf(
"Perú", "Sillón", "Amor", "Papel", "Reloj",
"Avestruz", "Anís", "Olla", "Unicornio", "Dado"
)
val (vowel, consonant) = words.partition { it.first().isVowel() }
println(
"""
Promedio vocales = ${calculateAvg(vowel)}
Promedio consonantes = ${calculateAvg(consonant)}
""".trimIndent()
)
}
private fun calculateAvg(words: List<String>) = words
.map { it.length }
.average()
private fun Char.isVowel() = when (this) {
'a', 'A', 'e', 'E', 'i', 'I', 'o', 'O', 'u', 'U' -> true
else -> false
}
Salida:
Promedio vocales = 5.8
Promedio consonantes = 4.8
El código anterior parte del arreglo words
con varias palabras. Para repartir los elementos en dos listas para aquellas que comienzan con vocal o consonante usamos partition()
.
El predicado que genera la división es expresado con una lambda que evalúa si la primera posición (first()
) es una vocal. La función de extensión Char.isVowel()
comprueba la igualdad de los literales de carácter que representan a las vocales.
El resultado de la división se desestructura en las listas vowel
y consonant
. Ambas se pasan como parámetro en la función calculateAvg()
, donde se mapea la lista en el tamaño de cada palabra y luego se calcula su media con average()
.