Как правильно удалить элементы из изменяемой карты scala с помощью предиката

Как это сделать, не создавая новых коллекций? Есть ли что-то лучше этого?

val m = scala.collection.mutable.Map[String, Long]("1" -> 1, "2" -> 2, "3" -> 3, "4" -> 4)
m.foreach(t => if (t._2 % 2 == 0) m.remove(t._1))
println(m)

P.S. в Скала 2.8


person Oleg Galako    schedule 23.03.2010    source источник
comment
В вопросах о коллекциях следует указать, требуется ли ответ 2,7 или 2,8.   -  person Randall Schulz    schedule 23.03.2010
comment
Пользуюсь 2.8 довольно давно, уже забыл про 2.7. Спасибо, добавил P.S.   -  person Oleg Galako    schedule 24.03.2010
comment
Есть тег Scala-2.8, который вы можете добавить как указание на то, что это конкретный вопрос 2.8.   -  person ams    schedule 24.03.2010
comment
Спасибо, заменил предикат на него   -  person Oleg Galako    schedule 25.03.2010


Ответы (3)


retain делает то, что вы хотите. В 2.7:

val a = collection.mutable.Map(1->"one",2->"two",3->"three")
a: scala.collection.mutable.Map[Int,java.lang.String] = 
  Map(2 -> two, 1 -> one, 3 -> three)

scala> a.retain((k,v) => v.length < 4)   

scala> a
res0: scala.collection.mutable.Map[Int,java.lang.String] =
  Map(2 -> two, 1 -> one)

Тоже работает, но думаю еще в процессе, в 2.8.

person Rex Kerr    schedule 23.03.2010
comment
Похоже, что функция сохранения устарела в версии 2.8: scala-lang.org/archives/downloads/distrib/files/nightly/docs/ устарело: нельзя вывести тип из-за сохранения в Iterable. - person Oleg Galako; 23.03.2010
comment
Верно; возможно, им придется переименовать его или придумать какой-нибудь другой обходной путь. Я не думаю, что он просто исчезнет; это было бы как-то глупо. Я интерпретирую это устаревание как изменяющееся, может измениться. - person Rex Kerr; 23.03.2010
comment
Похоже, отмену удалят. Так что ответ правильный. - person Oleg Galako; 28.03.2010

Согласно изменяемой карте Scala странице справки, вы может удалить один элемент с помощью -= или remove, например:

val m = scala.collection.mutable.Map[String, Long]("1" -> 1, "2" -> 2, "3" -> 3, "4" -> 4)
m -= "1" // returns m
m.remove("2") // returns Some(2)

Разница в том, что -= возвращает исходный объект карты, а remove возвращает параметр, содержащий значение, соответствующее удаленному ключу (если он был).

Конечно, как показывают другие ответы, если вы хотите удалить многие элементы на основе условия, вам следует изучить сохранение, фильтрацию и т. д.

person Jonathan Stray    schedule 18.10.2012

Если вы используете immutable.Map, в 2.7 это может быть что-то вроде:

def pred(k: Int, v: String) = k % 2 == 0

m --= (m.filter(pred(_, _)).keys

Поскольку нет доступного метода retain. Очевидно, что в этом случае m должен быть объявлен как var

person oxbow_lakes    schedule 23.03.2010
comment
Если вы используете неизменяемую карту и, следовательно, должны создать новую, довольно легко просто отфильтровать с отрицанием предиката. - person Randall Schulz; 23.03.2010
comment
Действительно, это правда: все зависит от того, что вы считаете более читаемым в данной ситуации. - person oxbow_lakes; 23.03.2010