Función slice En Kotlin

ANUNCIO
Loading...

En este tutorial aprenderás a cómo usar la función slice en Kotlin con la finalidad de seleccionar los elementos de una colección, según los índices pasados como argumento.

Función slice()

La función de extensión slice() retorna los elementos de una colección especificados por sus índices. Es decir, toma como parámetro una colección de índices enteros (IntRange o Iterable<Int>) para seleccionar los ítems y luego arroja como resultado instancia de List<T>. Las siguientes sintaxis muestran esta definición:

// slice() en arreglos genéricos fun <T> Array<out T>.slice(indices: IntRange): List<T> fun <T> Array<out T>.slice(indices: Iterable<Int>): List<T> // slice() en colecciones fun <T> List<T>.slice(indices: IntRange): List<T> fun <T> List<T>.slice(indices: Iterable<Int>): List<T>
Lenguaje del código: Kotlin (kotlin)

Considera la lista de enteros L = [1, 2, 3, 4, 5] y el uso de la función slice() en al siguiente ilustración:

Ejemplo de la función slice en Kotlin

Al usar como parámetro el rango 0..1 estamos indicando que deseamos obtener los elementos con el índice 0 y 1 de la lista. Lo que resulta en la nueva lista R = [1, 2]. El siguiente código muestra la representación de este escenario:

fun main() { val L = listOf(1, 2, 3, 4, 5) val R = L.slice(0..1) println(R) }
Lenguaje del código: Kotlin (kotlin)

Salida:

[1, 2]
Lenguaje del código: JSON / JSON con comentarios (json)

El rango anterior acota solo dos valores. Esta forma no aprovecha el poder de la clase IntRange, por lo podrías usar un conjunto para mejorar la legibilidad:

val R = L.slice(setOf(0, 1))
Lenguaje del código: Kotlin (kotlin)

Obtener Los Tres Elementos Centrales De Un Arreglo

Veamos otro ejemplo de la función slice() en arreglos.

Tomemos como ilustración un arreglo de enteros del cual deseamos obtener los tres elementos del centro. Luego de ello, se debe calcular el elemento menor de los tres.

fun main() { val numbers = listOf(3, 0, 1, 5, 2, 6, 1) // 1 val centerOfNumbers = numbers.size / 2 // 2 val centerIndices = centerOfNumbers - 1..centerOfNumbers + 1 // 3 val threeInTheCenter = numbers.slice(centerIndices) // 4 println("El valor más pequeño de $threeInTheCenter es ${threeInTheCenter.minOrNull()}") // 5 }
Lenguaje del código: Kotlin (kotlin)

Salida:

El valor más pequeño de [1, 5, 2] es 1
Lenguaje del código: CSS (css)

Solución:

  1. En esta línea se declara el arreglo de enteros numbers. El tamaño elegido es de siete para acomodar a nuestra conveniencia de la obtención del centro.
  2. Calculamos el centro dividiendo el tamaño de numbers por 2.
  3. Declaramos un rango con los tres índices del centro. El límite inferior será el centro menos la unidad y el superior el centro más la unidad.
  4. Obtenemos los elementos en el centro pasando centerIndices a la función slice(), invocada desde numbers.
  5. Imprimimos un mensaje que indique cual es el valor mínimo de los elementos del centro. Para obtener dicha cantidad usamos la función minOrNull(). Como es evidente, el resultado será el literal 1.

Eliminar Elementos Seleccionados

Pensemos en un programa que permite ver una lista de archivos disponibles al usuario. Basado en ello se desea implementar una característica que permita seleccionar archivos y luego enviarlos a un servidor.

La siguiente es la simulación en consola de este comportamiento:

val files = mutableListOf( "proyecto1.rar", "test.txt", "datos2021.xls", "otros.pdf", "ingresos.txt" ) fun main() { showFiles() var isInvalidUserInput = true while (isInvalidUserInput) { print("Escriba los índices: ") val fileIndices = processUserInput(readLine()) if (fileIndices.isNotEmpty()) { isInvalidUserInput = false sendFiles(fileIndices) } else { println("¡Entrada inválida!\n") } } } private fun showFiles() { files.forEachIndexed { index, s -> println("${index + 1}. $s") } } private fun processUserInput(userInput: String?) = try { convertUserInput(userInput) } catch (e: Exception) { emptySet() } private fun sendFiles(fileIndices: Set<Int>) { val selectedFiles = files.slice(fileIndices) println("Archivos a enviar:$selectedFiles") } private fun convertUserInput(userInput: String?): Set<Int> { if (userInput.isNullOrBlank()) { throw RuntimeException() } return if (isASingleIndex(userInput)) { convertInputToIndex(userInput) } else { val inputParts = splitIntoIndices(userInput) convertInputToIndices(inputParts) } } private fun isASingleIndex(cleanInput: String) = cleanInput.length == 1 private fun convertInputToIndex(cleanInput: String): Set<Int> { val index = cleanInput.trim().toInt() - 1 return if (isValidIndex()(index)) { setOf(index) } else { throw RuntimeException() } } private fun splitIntoIndices(userInput: String): List<String> = userInput.split(',') private fun convertInputToIndices(inputParts: List<String>): Set<Int> { val integerParts = inputParts.map { it.trim().toInt() - 1 } return integerParts.filter(isValidIndex()).toSet() } fun isValidIndex() = { i: Int -> i in 0..files.size }
Lenguaje del código: Kotlin (kotlin)

Salida:

1. proyecto1.rar 2. test.txt 3. datos2021.xls 4. otros.pdf 5. ingresos.txt Escriba los índices: 1,3,5 Archivos a enviar:[proyecto1.rar, datos2021.xls, ingresos.txt]
Lenguaje del código: CSS (css)

La solución escrita en la función main() consiste de un bucle while que se ejecuta mientras la entrada del usuario sea inválida.

El bucle comienza con la impresión de los archivos disponibles con showFiles() y luego pide al usuario los índices para seleccionar los elementos a enviar.

La entrada del usuario es procesada con processUserInput(). Donde se convertirá la entrada con convertUserInput() en un Set<Int> de índices.

Si es un solo elemento, entonces convertimos con convertInputToIndex(), de lo contrario con convertInputToIndices() para realizar un split() según el delimitador coma (',').

Al final del procesamiento, el bucle while evalúa si hubo un resultado que no sea vacío, Si es así entonces mostramos los archivos a enviar en sendFiles(). Aquí usamos a slice() para tomar los índices construidos e imprimirlos en pantalla.

Si no se cumple la condición, entonces se imprimirá un mensaje sobre que la entrada es inválida y así intentar de nuevo.

¿Ha sido útil esta publicación?