scala Удалить (на месте) все элементы ListBuffer, которые удовлетворяют условию - PullRequest
15 голосов
/ 11 декабря 2010

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

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

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

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

Это

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

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

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

Ответы [ 2 ]

6 голосов
/ 11 декабря 2010

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

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

println(lb)
// outputs: ListBuffer(1, 3, 5)
5 голосов
/ 12 декабря 2010

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

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

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

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

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

...