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

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

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

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

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

это

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

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

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

2 ответа

Решение

Вы не можете сделать это эффективно, к сожалению. Реализация --=(xs: TraversableOnce[A]) есть (в развернутом виде; фактический код более компактен)

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

что столь же неэффективно, как делать это по одному (то есть это O(n*m) где n длина исходного списка и m количество элементов для удаления).

В общем, изменяемые коллекции не имеют такого полного и мощного набора методов, как неизменяемые. (То есть у них есть все замечательные методы, используемые в неизменяемых коллекциях, но относительно немного их собственных.)

Поэтому, если вы не удаляете очень мало объектов, вам, вероятно, лучше отфильтровать список, чтобы создать новый.

Вы можете объединить два и сделать следующее:

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

println(lb)
// outputs: ListBuffer(1, 3, 5)
Другие вопросы по тегам