2010-12-11 6 views
15

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

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

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

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

Это

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

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

Как я должен это делать?

+0

См. Также http://stackoverflow.com/questions/2803085/iterators-for-mutable-collections-in-scala –

ответ

5

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

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

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

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

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

+3

«изменчивые коллекции не обладают таким полным и мощным набором методов, как неизменные». Да. Это очень жаль. Функциональное программирование может быть большим, но иногда изменчивая структура данных действительно то, что я хочу, и относительно скудная поддержка многопользовательских операций немного разочаровывает –

6

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

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

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

Отлично. Наверное, глупо, но как получилось? Фильтр возвращает итератор, а не список? Или TraversableOnce означает, что список достаточно хорош, как итератор для - =? –

+0

'TraversableOnce' более общий, чем итератор. Это обычный суперкласс как «Traversable» (на котором основаны все коллекции), так и «Итератор». –

+0

См. Http://www.scala-lang.org/docu/files/collections-api/collections.html –

Смежные вопросы