2010-12-11 16 views
15

Tengo un ListBuffer. Quiero eliminar todos los elementos que cumplen una determinada condición.scala Eliminar (en su lugar) todos los elementos de un ListBuffer que cumplan con una condición

Pude iterar sobre él y eliminar cada elemento. ¿Pero qué dice Scala acerca de mutar una lista sobre la que estás iterando? ¿Funcionará, o eliminará los elementos incorrectos/no devolverá todos los elementos? (Un intento rápido con el REPL sugiere que sí, se equivocará)

Pude llamar repetidas veces a find y luego eliminar el elemento encontrado hasta que no encontré nada más, pero eso suena ineficaz.

.filter me devolverá un nuevo ListBuffer sin los elementos, pero quiero hacerlo en su lugar.

Este

def --= (xs: TraversableOnce[A]) : ListBuffer.this.type 
Removes all elements produced by an iterator from this list buffer. 

parece prometedor, pero no puedo ver bien cómo usarlo aquí

¿Cómo debo hacer esto?

+0

Véase también http://stackoverflow.com/questions/2803085/iterators-for-mutable-collections-in-scala –

Respuesta

5

No se puede hacer esto de manera eficiente, por desgracia. La implementación de --=(xs: TraversableOnce[A]) es (en forma expandida, el código real es más compacto)

xs foreach (x => this -= x) ; this 

que es tan ineficaz como hacerlo de uno en uno (es decir, es O(n*m) donde n es la longitud de la lista original y m es la cantidad de elementos para eliminar).

En general, las colecciones mutables no tienen un conjunto de métodos tan completo y poderoso como los inmutables. (Es decir, tienen todos los maravillosos métodos utilizados en colecciones inmutables, pero relativamente pocos).

Así que a menos que esté eliminando muy pocos objetos, probablemente sea mejor que filtre la lista para crear uno nuevo.

+3

"las colecciones mutables no tienen un conjunto de métodos tan completo y poderoso como los inmutables". Sí. Esto es una lástima. La programación funcional puede ser genial, pero a veces una estructura de datos mutable es realmente lo que quiero y el apoyo relativamente escaso para las operaciones solo multables es un poco decepcionante –

6

Se puede combinar los dos y hacer lo siguiente:

val lb = ListBuffer(1,2,3,4,5,6) 
lb --= lb.filter(_ % 2 == 0) 

println(lb) 
// outputs: ListBuffer(1, 3, 5) 
+0

Perfecto. Probablemente ser tonto, pero ¿cómo es que eso funciona? ¿El filtro devuelve un iterador en lugar de una lista? ¿O significa el TraversableOnce que una lista es lo suficientemente buena como un iterador para - =? –

+0

'TraversableOnce' es más general que un iterador. Es una superclase común tanto de 'Traversable' (en el que se basan todas las colecciones) como de' Iterator'. –

+0

Ver http://www.scala-lang.org/docu/files/collections-api/collections.html –

Cuestiones relacionadas