Función windowed En Kotlin

En este tutorial aprenderás sobre la función windowed en Kotlin, con el objetivo de obtener rangos de elementos con un tamaño dado, dentro de una colección.

Función windowed()

La función de extensión windowed() retorna una lista de capturas a partir de un rango de elementos llamado «ventana». Este rango se va deslizando entre los elementos de la colección invocadora con el propósito de crear los grupos.

fun <T> Iterable<T>.windowed(
    size: Int,
    step: Int = 1,
    partialWindows: Boolean = false
): List<List<T>>

Los parámetros que toma son:

  • size: Determina la cantidad de elementos de la colección que la ventana abarca
  • step: Determina el avance con que se mueve la ventana dentro de la colección
  • partialWindows: Establece si las ventanas parciales resultantes se conservan en el retorno

Ejemplo De windowed()

Juguemos un poco con la flexibilidad de windowed() aplicándola sobre un rango de enteros del 1 al 5.

fun main() {
    val fromOneToFive = 1..5
    println(fromOneToFive.windowed(3)) // 1
    println(fromOneToFive.windowed(3,2)) // 2
    println(fromOneToFive.windowed(3,partialWindows = true)) // 3
}

Salida:

[[1, 2, 3], [2, 3, 4], [3, 4, 5]]
[[1, 2, 3], [3, 4, 5]]
[[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5], [5]]

Veamos de qué se tratan los ejemplos:

  1. Pasamos size = 3. Se obtienen 3 capturas, debido a que la ventana solo se pudo mover entre los números 1, 2 y 3 para completar rangos que satisfagan el tamaño 3.
  2. Pasamos size = 3 y step = 2. Aquí solo obtenemos dos capturas porque el primer grupo comienza por 1, y al avanzar 2 elementos, el segundo grupo va de 3 a 5, lo que significa que ya no hay más combinaciones adecuadas.
  3. Pasamos size = 3 y partialWindows = true. El resultado es el mismo que en (1), pero esta vez se incluyen las capturas parciales al deslizar hasta 5. Obviamente el tamaño de las ventanas parciales será diferente, porque no se disponen de elementos para completar rangos de 3.

Función windowed() Con Transformación

En el caso que quieras usar una transformación sobre cada rango de elementos obtenido por windowed(), usa su versión sobrecargada, cuyo cuarto parámetro es un tipo función para aplicar transformación.

fun <T, R> Iterable<T>.windowed(
    size: Int,
    step: Int = 1,
    partialWindows: Boolean = false,
    transform: (List<T>) -> R
): List<R>

Esto te permitirá obtener una lista de todas las transformaciones aplicadas a las ventanas generadas.

Calcular Promedios Con windowed()

Considera un programa que ha obtenido los datos planos de una fila en una hoja de cálculo. Se sabe de antemano que la fila contiene datos decimales que están agrupados de a 3 elementos y cada conjunto está separado de otro por un espacio en la fila.

Basado en ello obtén los promedios de cada conjunto e imprímelos:

fun main() {
    val rowData = listOf(
        "2.6", "3.3", "1.2", "",
        "5.0", "0.3", "2.1", "",
        "3.6", "3.2", "4.0", ""
    )
    val averages = rowData.windowed(3, 4) { row ->
        val cellValues = row.map { cell -> cell.toDouble() }
        cellValues.average()
    }
    averages.forEach { println("%.2f".format(it)) }
}

Salida:

2,37
2,47
3,60

Como ves, existe una lista de Strings llamada rowData que representa la lectura de la fila en la hoja de cálculo.

Ya que necesitamos extraer grupos de tres e ignorar el cuarto elemento entre ellos, pasamos como argumentos a size = 3 y step = 4.

Esto nos permite escribir una función lambda con una transformación que se basa en el uso de map() para convertir el valor de cada celda en Double. Y finalmente encontrar la media con average() para cada captura obtenida.

Al final imprimimos cada elemento de los promedios con forEach() y usando un formato de dos posiciones decimales con format().

Ú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!