En este tutorial aprenderás a usar la función sum
en Kotlin para obtener la suma de los elementos de una colección numérica, a través de ejemplos. Adicionalmente verás las variaciones sumOf()
, sumBy()
y sumByDouble()
para usar un selector que te permita mapear colecciones para disponerlas a la sumatoria.
Función sum()
La función de extensión sum()
retorna en la sumatoria de todos los elementos de un arreglo o colección de números. A continuación se muestran algunas variaciones de su sintaxis:
// sum() en Arreglos
fun IntArray.sum(): Int
fun DoubleArray.sum(): Double
// sum() en colecciones
fun Iterable<Int>.sum(): Int
fun Iterable<Double>.sum(): Double
Por ejemplo, usemos la función sum()
en código Kotlin para realizar la sumatoria de:
- Los elementos de un arreglo de números reales
- Un rango del 1 al 10
- Una lista de números
Long
generados aleatoriamente entre 20 y 100
import kotlin.random.Random
fun main() {
val decimals = doubleArrayOf(1.1, 2.2, 4.5, -1.2)
println("sum${decimals.contentToString()} = ${decimals.sum()}")
val fromOneToTen = 1..10
println("sum[$fromOneToTen] = ${fromOneToTen.sum()}")
val randomNumbers = List(5) { Random.nextLong(20, 100) }
println("sum$randomNumbers = ${randomNumbers.sum()}")
}
Salida:
sum[1.1, 2.2, 4.5, -1.2] = 6.6000000000000005
sum[1..10] = 55
sum[60, 33, 63, 59, 63] = 278
Función sumOf()
La función sumOf()
toma como parámetro una función de selección (selector
) y se la aplica a cada elemento de la colección invocadora. El resultado final es el sumatorio de todos estos resultados de conversión. Las siguientes son algunas muestras de su sintaxis
// sumOf() en arreglos con resultado Double
fun <T> Array<out T>.sumOf(selector: (T) -> Double): Double
// sumOf() en colecciones con resultado Int
fun <T> Iterable<T>.sumOf(selector: (T) -> Int): Int
// sumOf() en strings con resultado Double
public inline fun CharSequence.sumOf(
selector: (Char) → Double
): Double
Como ves, a diferencia de sum()
, la función sumOf()
es genérica, por lo que la colección no tiene que ser de tipo numérico. Lo importante es usar al selector para especificar el mapeado apropiado a sumar y retornar.
Considera el modelado de los vendedores de una compañía y la cantidad de ventas realizadas en el mes.
data class Salesman(val name: String, val sales: Int)
Dada una lista de vendedores, obtener el total de ventas realizado por todos los agentes:
fun main() {
val persons = listOf(
Salesman("Jackson", 18),
Salesman("Miguel", 10),
Salesman("Milena", 16),
Salesman("Rosa", 40)
)
val totalSales = persons.sumOf { it.sales }
println("Total de ventas: $totalSales")
}
Salida:
Total de ventas: 84
En el ejemplo anterior la función sumOf()
es perfecta porque nos permite pasar una función lambda que acceda a la propiedad sales
para usarla como ejemplar en la suma.
Función sumBy()
La función sumBy()
hace exactamente lo que sumOf()
, solo que el cuerpo del selector siempre es de tipo Int
, al igual que el valor de la suma retornada.
// sumBy() en arreglos de tipo T
fun <T> Array<out T>.sumBy(selector: (T) -> Int): Int
// sumBy() en colecciones
inline fun <T> Iterable<T>.sumBy(selector: (T) -> Int): Int
// sumBy() en strings
public inline fun CharSequence.sumBy(
selector: (Char) → Int
): Int
Por ejemplo, obtengamos la suma total de todos los códigos numéricos de los caracteres del string "Develou"
.
fun main() {
val string = "Develou"
val codesSum = string.sumBy { it.toInt() }
println("Suma de códigos: $codesSum")
}
Salida:
Suma de códigos: 724
Ya que el selector es de tipo función (Char) -> Int
, el único resultado aceptable es un entero, por lo que usamos la función toInt()
para permitir la agregación de cada carácter a la suma.
Función sumByDouble()
La función sumByDouble()
tiene el mismo propósito que sumBy()
, solo que esta vez el cuerpo del selector y el retorno son de tipo Double
en cada forma de sintaxis:
// sumByDouble() en arreglos de tipo T
fun <T> Array<out T>.sumByDouble(
selector: (T) -> Double
): Double
// sumByDouble() en colecciones
fun <T> Iterable<T>.sumByDouble(
selector: (T) -> Double
): Double
Supón que deseas desarrollar una sumatoria de los inversos de una lista de números enteros y deseas imprimir el resultado en su versión decimal.
fun main() {
val integers = listOf(1, 2, 3, 4, 5)
val multiplicativeInverseSum = integers.sumByDouble { (1.0 / it) }
val inversesInStringForm = integers.joinToString(prefix = "[", postfix = "]") { "1/$it" }
println("sum$inversesInStringForm = $multiplicativeInverseSum")
}
Salida:
sum[1/1, 1/2, 1/3, 1/4, 1/5] = 2.283333333333333
En el ejemplo anterior usamos a la función sumByDouble()
pasando como selector a la división entre el literal 1.0
y cada entero de integers
. Esta operación hace explicita la conversión a Double
para satisfacer el tipo (Int) -> Double
esperado.
Finamente transformamos la lista para que luzca con la representación fraccionaria de cada elemento en inversesInStringForm
y así imprimir el resultado final de multiplicativeInverseSum
.