En este tutorial te mostraremos el uso de la función minOrNull
en Kotlin para determinar el elemento con el valor más pequeño en una colección. Adicionalmente cubriremos otras variaciones como minByOrNull()
, minWithOrNull()
y minOf()
.
La Función minOrNull()
La función de extensión minOrNull()
retorna el valor más pequeño de la colección que sirva como objeto invocador. Si la colección está vacía, entonces obtendrás null
, es por eso que su sintaxis tiene usa tipos anulables.
// minOrNull() en arreglos
fun Array<out Double>.minOrNull(): Double?
fun Array<out Float>.minOrNull(): Float?
fun <T : Comparable<T>> Array<out T>.minOrNull(): T?
// minOrNull() en iterables
fun Iterable<Double>.minOrNull(): Double?
fun Iterable<Float>.minOrNull(): Float?
fun <T : Comparable<T>> Iterable<T>.minOrNull(): T?
// minOrNull() en CharSecuences
fun CharSequence.minOrNull(): Char?
Considera la lista de enteros L=[-2, -1, 0, 1]
como objeto de estudio. Si aplicásemos minOrNull()
sobre esta colección el resultado será el entero más a la izquierda de la recta numérica, o sea el valor -2.
En código Kotlin, el ejemplo se vería así:
fun main() {
val numbers = listOf(-2, -1, 0, 1)
println(numbers.minOrNull()) // -2
}
Recuerda que si la colección está vacía el resultado será null
:
fun main() {
println(emptyList<Int>().minOrNull()) // null
}
O en el caso de que tu lista tenga a la constante NaN, el resultado será ella:
fun main() {
val doubles = doubleArrayOf(-1.0, 1.2, 3.5, 0.0, Double.NaN)
println(doubles.minOrNull()) // NaN
}
Función minByOrNull()
Esta variación toma como parámetro un tipo función de selección del valor que debe ser comparado.
Considera una clase de datos que representa el nombre y extensión en kilómetros de diferentes ríos en el mundo.
data class River(val name:String, val length:Int)
A partir de una lista de ríos que se nos provee, se requiere determinar cual tiene la menor longitud:
un main() {
val rivers = listOf(
River("Nilo", 6690),
River("Mississippi", 6270),
River("Amazonas", 6387),
River("Negro", 2250)
)
println(rivers.minByOrNull { it.length })
}
Salida:
River(name=Negro, length=2250)
Como ves, la solución consiste en usar minByOrNull()
pasando como elemento selector al atributo length
. El resultado final es el río Negro con la menor longitud.
La función lambda que pases debe tener como cuerpo una expresión cuyo resultado implemente la interfaz Comparable
.
Función minWithOrNull()
Retorna el elemento que tenga el valor más pequeño de una colección según el parámetro Comparator
que proveas. Si la colección está vacía entonces el resultado será null
.
Tomemos como ejemplo un mapa con un mapa de frutas que contiene pares del nombre y cantidad de vitamina C en una porción de 100g. Determinemos cual es la fruta con la menor cantidad del nutriente con minWithOrNull()
:
fun main() {
val fruitsAndVitaminC = mapOf(
"Aguacate" to 10.0,
"Berenjena" to 2.2,
"Limones" to 53.0,
"Piña" to 47.8
)
val fruit = fruitsAndVitaminC.minWithOrNull(compareBy { it.value })
println(fruit)
}
Salida:
Berenjena=2.2
Recuerda que Comparator<T>
es el alias de la interfaz original de Java con el mismo nombre. Esta provee un método para imponer el orden de instancias del tipo T
.
El código anterior usa la función constructora compareBy()
para crear una instancia Comparator
, a través de una función lambda que establece orden comparable según la cantidad de vitamina C. Por ellos usamos a it.value
como valor final del bloque.
Función minOf()
La función minOf()
hace exactamente lo mismo que minByOrNull()
solo que en vez de retornar null
cuando la colección es vacía, esta arroja una excepción del tipo NoSuchElementException
.
Por ejemplo, supón que deseas recolectar consultas en una lista mutable de Strings y deseas ver cuál es la menor en cuestión de orden alfabético. Si no existen consultas recolectadas, entonces mostrar un mensaje de aviso.
un main() {
val searchQueries = mutableListOf<String>()
// Se añaden elementos...
searchQueries += "Tablet"
searchQueries += "Carro"
searchQueries += "Juguetes"
val query = try {
searchQueries.minOf { it }
} catch (e: NoSuchElementException) {
"No existen consultas"
}
println(query)
}
Salida:
Carro
La solución consiste en usar la función minOf()
sobre la lista searchQueries
con una expresión try..catch
. Si la lista es vacía, entonces establecemos el texto de aviso.
Puedes comprobar el paso por catch
si comentas las tres líneas de operaciones de agregación. Así tendrás la impresión:
No existen consultas