Estoy tratando de filtrar ciertos elementos de una lista y fusionarlos en la lista final en un orden específico. El primer fragmento de código parece ineficiente ya que crea 2 listas para filtrar y luego itera sobre ellas, sin embargo, ese código funciona. El segundo fragmento está tratando de combinar ambos filtros, sin embargo, el operador del mapa no está agregando elementos a la lista otherNums.
¿Podría alguien ayudarme a entender por qué sucede esto?
Fragmento 1:
fun main() { val favItem = 0 val list = listOf(11, 12, 13, 2,3,4,5,6,7,10, favItem) val greaterThan10 = list.filter{item -> item > 10} val otherNums = list.asSequence().filter{item -> item != favItem}.filter{item -> item < 10} println(" $greaterThan10") //the list is filled with proper numbers println("merged list ${greaterThan10.plus(favItem).plus(otherNums)}") }Resultado:
[11, 12, 13] merged list [11, 12, 13, 0, 2, 3, 4, 5, 6, 7]Fragmento 2:
fun main() { val favItem = 0 val list = listOf(11, 12, 13, 2,3,4,5,6,7,10, favItem) val greaterThan10 = mutableListOf<Int>() val otherNums = list.asSequence().filter{item -> item != favItem}.map{ if(it > 10) { greaterThan10.add(it) } it } .filter{item -> item != 10} println("$greaterThan10") // the list is empty println("merged list ${greaterThan10.plus(favItem).plus(otherNums)}") }Resultado:
[] merged list [0, 11, 12, 13, 2, 3, 4, 5, 6, 7]En su segundo fragmento, la lista de greaterThan10 está vacía debido al comportamiento perezoso de las secuencias, una secuencia se itera solo cuando se encuentra una operación de terminal como toList() o sum() .
En su caso, la secuencia se itera cuando escribe .plus(otherNums) . List + Sequence produce una List . Si imprime su lista de greaterThan10 de 10 después de imprimir la lista fusionada, la encontrará poblada.
Por cierto, no necesitas una Sequence aquí. Dos casos principales en los que las secuencias son más eficaces que las listas son:
map , filter , etc. Con Iterable se crean muchos Iterable intermedios que consumen más memoria,take() , contains() , first() , etc., es decir, cuando no es necesario iterar toda la colección para obtener el resultado final.Según los documentos,
La naturaleza perezosa de las secuencias agrega una sobrecarga que puede ser significativa cuando se procesan colecciones más pequeñas o se realizan cálculos más simples. Por lo tanto, debe considerar tanto Sequence como Iterable y decidir cuál es mejor para su caso.
Para la solución final, creo que puede usar su fragmento 1. Eso me parece bien, solo elimine la asSequence innecesaria y combine los dos filter en uno.
fun main() { val favItem = 0 val list = listOf(11, 12, 13, 2, 3, 4, 5, 6, 7, 10, favItem) val greaterThan10 = list.filter {item -> item > 10} val otherNums = list.filter { it != favItem && it <= 10 } println(" $greaterThan10") println("merged list ${greaterThan10 + favItem + otherNums}") } Creo que usar el filter es mejor que minus en las listas, ya que este último tiene una complejidad de tiempo cuadrática en el peor de los casos (si no recuerdo mal). Escribí un pequeño ejemplo para demostrar la diferencia. Ejecute esto varias veces para ver la diferencia.
Además, como @IvoBeckers mencionó en el comentario, "Si la lista original no tiene un elemento favorito, este método también le agregará uno. Y si la lista tiene varios elementos favoritos, este método lo reemplazará con uno solo".
val favItem = 0 val list = listOf(11, 12, 13, 2, 3, 4, 5, 6, 7, 10, favItem) val greaterThan10 = list.filter { it > 10 } val otherNums = list - greaterThan10.toSet() - favItem println("greaterThan10: $greaterThan10") // [11, 12, 13] println("otherNums: $otherNums") // [2, 3, 4, 5, 6, 7, 10] println("merged list: ${greaterThan10 + favItem + otherNums}")Editar: reemplazó .minus(...) con -. Gracias al comentario de @Ivo Beckers.
val favItem = 0 val list = listOf(11, 12, 13, 2, 3, 4, 5, 6, 7, 10, favItem) val (greaterThan10, otherNums) = list // destructuring assignment .filter { it != favItem } // filter out favItem .groupBy { it > 10 } // create two groups .toSortedMap { o1, _ -> if (o1) -1 else 1 } // sort groups in the order [true, false] .map { it.value.toList() } // return the two lists println("greaterThan10: $greaterThan10") println("otherNums: $otherNums") println("merged list: ${greaterThan10 + favItem + otherNums}")