Question

I have a ListBuffer. I want to remove all elements that meet a certain condition.

I could iterate over it and remove each element. But what doe Scala say about mutating a list that you are iterating over? Will it work, or will it delete the wrong elements/not return all elements? (A quick attempt with the REPL suggests that yes, it will mess up)

I could repeatedly call find and then remove the found element until I don't find any more, but that sounds inefficient.

.filter will return me a new ListBuffer without the elements, but I want to do it in place.

This

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

looks promising but I can't quite see how to use it here

How should I do this?

Was it helpful?

Solution

You can't do this efficiently, unfortunately. The implementation of --=(xs: TraversableOnce[A]) is (in expanded form; the actual code is more compact)

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

which is just as inefficient as doing it one at a time (i.e. it's O(n*m) where n is the length of the original list and m is the number of items to remove).

In general, the mutable collections don't have as full and powerful a set of methods as the immutable ones. (That is, they have all the wonderful methods used on immutable collections, but relatively few of their own.)

So unless you're removing very few objects, you're probably better off filtering the list to create a new one.

OTHER TIPS

You could combine the two and do the following:

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

println(lb)
// outputs: ListBuffer(1, 3, 5)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top