Search code examples
scalaarraybuffer

scala ArrayBuffer remove all elements with a predicat


Scala is very elegant in filtering immutable sequences:

var l = List(1,2,3,4,5,6)
l = l.filter(_%2==1)

But how do I do this with a mutable collections like ArrayBuffer? All I found is the removal of single elements or slices, or remove elements from another sequence, but nothing that removes elements given by a predicate.

Edit: I was hoping to find something similar tho this:

trait Removable[A] extends Buffer[A]{ 
  def removeIf(p: A => Boolean){
    var it1 = 0
    var it2 = 0

    while(it2 < length){
      if( p( this(it2) ) ){
        it2 += 1;
      } 
      else {
        this(it1) = this(it2)
        it1 += 1;
        it2 += 1;
      }
    }

    trimEnd(it2-it1)
  }
}

this filters in linear time and can be mixed into any Buffer, but only ArrayBuffer makes sense, on ListBuffers it would be slow, because indexing does take linear time.


Solution

  • My guess is that it's more efficient to filter by building a new buffer, so you would normally just use filter and use its result. Otherwise you can write your own in-place filter method:

    def filterInPlace[A](b: collection.mutable.Buffer[A])(fun: A => Boolean): Unit = {
      var sz = b.size
      var i = 0; while(i < sz) {
        if (fun(b(i))) {
          i += 1
        } else {
          sz -= 1
          b.remove(i)
        }
      }
    }
    
    val b = collection.mutable.ArrayBuffer((1 to 6): _ *)
    filterInPlace(b)(_ % 2 == 1)
    println(b)