scala ArrayBuffer使用谓词删除所有元素

scala ArrayBuffer使用谓词删除所有元素,scala,arraybuffer,Scala,Arraybuffer,Scala在过滤不可变序列方面非常出色: var l = List(1,2,3,4,5,6) l = l.filter(_%2==1) 但是我如何处理像ArrayBuffer这样的可变集合呢? 我所发现的只是删除单个元素或片段,或者从另一个序列中删除元素,但并没有删除谓词给定的元素 编辑: 我希望能找到类似的东西: trait Removable[A] extends Buffer[A]{ def removeIf(p: A => Boolean){ var it1 = 0

Scala在过滤不可变序列方面非常出色:

var l = List(1,2,3,4,5,6)
l = l.filter(_%2==1)
但是我如何处理像ArrayBuffer这样的可变集合呢? 我所发现的只是删除单个元素或片段,或者从另一个序列中删除元素,但并没有删除谓词给定的元素

编辑: 我希望能找到类似的东西:

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)
  }
}
trait-Removable[A]扩展缓冲区[A]{
def removeIf(p:A=>Boolean){
变量it1=0
变量it2=0
而(it2<长度){
if(p(本(it2))){
it2+=1;
} 
否则{
此(it1)=此(it2)
it1+=1;
it2+=1;
}
}
trimEnd(it2-it1)
}
}

这种方法在线性时间内进行过滤,可以混合到任何缓冲区中,但只有ArrayBuffer才有意义,在ListBuffers上它会很慢,因为索引确实需要线性时间。

我的猜测是,通过构建一个新的缓冲区进行过滤更有效,所以您通常只需使用
过滤器
并使用其结果。否则,您可以编写自己的就地筛选方法:

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)
def filteringplace[A](b:collection.mutable.Buffer[A])(fun:A=>Boolean):单位={
var sz=b.size
var i=0;而(i
有人讨论过一套通过执行变异来工作的方法,但想出一套好的通用方法却异常困难,另一方面,对它的需求还不够

通常
with filter
就足够了,特别是当缓冲区最终转换为不可变结构时。的确,它并没有真正删除元素,但至少它没有创建新的ArrayBuffer对象。

这对我来说很有效,但只适用于clone(),因此仍然创建了一个新的ArrayBuffer:-)

但更好的方法是只创建一个新数组,其中包含您想要删除的元素(因此不复制整个缓冲区),然后删除它们:

scala> val buf = ArrayBuffer(1,2,3,4,5,6,7,8,9,10)
buf: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> buf filter { _ > 4 } foreach { buf -= _ }

scala> buf
res3: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)

使用
ArrayBuffer
也可以执行同样的操作。所有集合类都有相同的可用方法。

我想到了这个

import scala.collection.mutable

trait BufferUtils {
    import BufferUtils._
    implicit def extendMutableBuffer[T](org: mutable.Buffer[T]): ExtendedBuffer[T] = new ExtendedBuffer(org)
}

object BufferUtils extends BufferUtils {

    implicit class ExtendedBuffer[T](val org: mutable.Buffer[T]) extends AnyVal {
        def removeIf(pred: (T) => Boolean): Unit = {
            // target holds the index we want to move the next element to
            var target = 0

            for (i <- org.indices;
                 elem = org(i)
                 if !pred(elem)) {

                org(target) = elem
                target += 1
            }

            org.remove(target, org.size - target)
        }
    }

}
导入scala.collection.mutable
特征缓冲区{
导入BufferUtils_
隐式def extendedmutablebuffer[T](org:mutable.Buffer[T]):ExtendedBuffer[T]=新的ExtendedBuffer(org)
}
对象BufferUtils扩展了BufferUtils{
隐式类ExtendedBuffer[T](val org:mutable.Buffer[T])扩展AnyVal{
def removeIf(pred:(T)=>布尔值):单位={
//target保存我们要将下一个元素移动到的索引
var目标=0

因为(我想我的要求不够高,或者我的人太少了。@Rex我只是在等你实施它们并提交给Scala孵化器。:-)事实上,EPFL人员的资源有限,一些重要的东西被遗漏了。例如,看看
-save
的命运。我几乎主动提出在几个月前开始的scala辩论线程中自己编写它们。也许你是对的,需求太少,甚至不值得请其他人来实现它@Rex我以前曾与开源合作过,因此我可以向您介绍他们对开源的可能看法。建议很多,提供的帮助也很多。但是,很少有人会参与到另一个方面,任何添加到代码库的代码都会给在代码库上工作带来额外的负担。因此,即使是完整的实现也要谨慎考虑,但是,是的,我只有足够的时间去做那些有很好机会被使用的事情。是的,你的解决方案是可行的,但它会及时的O(n^2),因为每次删除都是对缓冲区的搜索和重新排列。我一直在寻找在O(n)中工作的东西。但我认为我需要自己做。我认为在可变情况下,它永远不会是O(n)。但是如果你做经典的不可变筛选,那么你就在O(n):-)。你的
filternplace
很慢,因为
b.remove(I)
是一种O(n)方法。
import scala.collection.mutable

trait BufferUtils {
    import BufferUtils._
    implicit def extendMutableBuffer[T](org: mutable.Buffer[T]): ExtendedBuffer[T] = new ExtendedBuffer(org)
}

object BufferUtils extends BufferUtils {

    implicit class ExtendedBuffer[T](val org: mutable.Buffer[T]) extends AnyVal {
        def removeIf(pred: (T) => Boolean): Unit = {
            // target holds the index we want to move the next element to
            var target = 0

            for (i <- org.indices;
                 elem = org(i)
                 if !pred(elem)) {

                org(target) = elem
                target += 1
            }

            org.remove(target, org.size - target)
        }
    }

}