Tengo la tarea de escribir una función usando fold (programación funcional) para contar la cantidad de elementos en una lista que cumplen con el predicado. Me dieron la firma de función fun <A> count(list<A>, predicate: (A) -> Boolean): Int . Fold no solo se utilizará como iteración, sino que también generará el valor de retorno. Así que traté de hacer esto:
fun <A> count(list: List<A>, predicate: (A) -> Boolean): Int { return list.fold(0) { acc, a -> if (predicate(a)) { return acc + 1 } return acc } }Escribí un println para comprobar si funciona:
println(count3(listOf (1, -2, 3, 10, -5, 8, 12), { it > 0 && it < 10 }))Sin embargo, obtuve el resultado 1 en lugar de 3 en la consola y no sé dónde está la falla. Entonces, ¿alguien tiene una idea de dónde está mi error o cómo puedo implementar la función en su lugar?
Y para que quede claro: Fold acumula un valor, comenzando por el valor inicial (en este caso 0) y aplicando la operación de izquierda a derecha al acumulador actual y cada elemento o me equivoco?
EDITAR (espero que esté bien editar una pregunta en lugar de hacer una nueva):
¿Es posible devolver una lista completa en lugar de solo un int? Acabo de encontrar ejemplos que devuelven números enteros o booleanos. Lo que probé: he usado la misma firma de función de arriba. Pero en lugar de devolver un Int, quiero devolver una lista:
fun <A> returnList(list: List<A>, predicate: (A) -> Boolean): List<A> { return list.fold(mutableListOf()) { acc, a -> if (predicate(a)) { acc.add(a) } else { acc } } } El problema que encontré es que acc.add(a) devuelve un booleano y no una lista, por lo que el IDE lo marca como un error. Entonces, ¿hay alguna manera de devolver una lista?
Gracias de antemano.
Pruébalo así:
fun <A> count(list: List<A>, predicate: (A) -> Boolean): Int { return list.fold(0) { acc, a -> if (predicate(a)) acc+1 else acc } } fun main(args: Array<String>) { val x = listOf<Int>( 1, -2, 3, 10, -5, 8, 12); println(count(x, { it > 0 && it < 10 })) }Mirar este sitio me dejó claro el cambio necesario.
¿Es esa forma necesaria porque el pliegue usa la recursividad de la cola? Interesante ver cuál es la razón.
Al decir return , devuelve la función de count completa. puedes usar return@fold en su lugar. asi como
fun <A> count(list: List<A>, predicate: (A) -> Boolean): Int { return list.fold(0) { acc, a -> if (predicate(a)) { return@fold acc + 1 } return@fold acc } }alternativamente y tal vez mejor es hacerlo así
fun <A> count(list: List<A>, predicate: (A) -> Boolean): Int { return list.fold(0) { acc, a -> if (predicate(a)) { acc + 1 } else { acc } } }la última expresión en una lambda es implícitamente también su valor de retorno
fun <A> count(list: List<A>, predicate: (A) -> Boolean): Int { return list.fold(0) { acc, a -> acc + predicate(a).run { if (this) 1 else 0 } } }