【问题标题】:scala Remove (in place) all elements of a ListBuffer that meet a conditionscala 移除(就地)ListBuffer 中满足条件的所有元素
【发布时间】:2011-05-24 00:16:17
【问题描述】:

我有一个 ListBuffer。我想删除所有满足特定条件的元素。

我可以遍历它并删除每个元素。但是 Scala 对改变你正在迭代的列表有什么看法?它会起作用,还是会删除错误的元素/不返回所有元素? (对 REPL 的快速尝试表明是的,它会搞砸的)

我可以反复调用 find,然后删除找到的元素,直到找不到更多,但这听起来效率很低。

.filter 将返回一个没有元素的新 ListBuffer,但我想就地执行。

这个

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

看起来很有希望,但我不太明白如何在这里使用它

我应该怎么做?

【问题讨论】:

标签: scala scala-2.8 listbuffer


【解决方案1】:

很遗憾,您无法有效地做到这一点。 --=(xs: TraversableOnce[A])的实现是(展开形式;实际代码更紧凑)

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

这与一次一个操作一样低效(即O(n*m),其中n 是原始列表的长度,m 是要删除的项目数)。

一般来说,可变集合没有像不可变集合那样完整和强大的一组方法。 (也就是说,它们拥有用于不可变集合的所有出色方法,但它们自己的相对较少。)

因此,除非您要删除 非常 个对象,否则最好过滤列表以创建一个新对象。

【讨论】:

  • “可变集合没有像不可变集合那样完整和强大的一组方法。”。是的。这是一个遗憾。函数式编程可能很棒,但有时可变数据结构确实是我想要的,而对仅可操作操作的相对微弱的支持有点令人失望
【解决方案2】:

您可以将两者结合起来并执行以下操作:

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

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

【讨论】:

  • 完美。可能是愚蠢的,但这是怎么回事?过滤器是否返回迭代器而不是列表?或者 TraversableOnce 是否意味着列表作为迭代器足以 --=?
  • TraversableOnce 比迭代器更通用。它是Traversable(所有集合都基于它)和Iterator 的共同超类。
  • 谢谢。 scaladoc 与描述它需要一个迭代器的描述相混淆......
  • 值得注意的是,这并不是超级高效 - 您正在从过滤器生成一个新的列表缓冲区,然后再次遍历原始集合以删除值。
猜你喜欢
  • 2021-09-13
  • 2021-06-07
  • 2013-03-06
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-13
  • 2021-12-15
相关资源
最近更新 更多