Scala Удалить (на месте) все элементы ListBuffer, которые удовлетворяют условию

У меня есть ListBuffer. Я хочу удалить все элементы, удовлетворяющие определенному условию.

Я мог бы перебрать его и удалить каждый элемент. Но что do Scala говорит о том, что вы перебираете список, который вы повторяете? Будет ли он работать, или он удалит неправильные элементы/не вернет все элементы? (Быстрая попытка с REPL предполагает, что да, это испортится)

Я мог неоднократно называть find, а затем удалять найденный элемент, пока я больше не нахожу, но это звучит неэффективно.

.filter вернет мне новый ListBuffer без элементов, но я хочу сделать это на месте.

Это

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

выглядит многообещающим, но я не могу понять, как его использовать здесь.

Как мне это сделать?

Ответы

Ответ 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)