Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 223
Arne Avatar asked Apr 05 '11 01:04

Arne


Video Answer


2 Answers

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)
like image 83
0__ Avatar answered Oct 16 '22 04:10

0__


There has been discussion about having a set of methods that work by performing mutation, but coming up with a good, generic set is surprisingly hard, and, on the other hand, there just hasn't been enough demand for it.

like image 34
Daniel C. Sobral Avatar answered Oct 16 '22 02:10

Daniel C. Sobral