Карта только с определенными ключами

что касается карт в Scala, если ms - (k, 1, m) возвращает карту, содержащую все отображения ms за исключением для любого отображения с заданными ключами, x, 1 и m.

тогда, какой оператор вернет карту всех отображений ms с только данные ключи, x, 1 и m. т. е. я ищу подмножество ms, где только K, 1 и m являются ключами.

это работает, но это ужасно:

scala> val originalMap = Map("age" -> "20", "name" -> "jack", "hobby" -> "jumping")
ms: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(age -> 20, name -> jack, hobby -> jumping)

scala> val interestingKeys = List("name", "hobby")
interesting: List[java.lang.String] = List(name, hobby)

scala> val notInterestingMap = originalMap -- interestingKeys
notInterestingMap: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(age -> 20)

scala> val interestingMap = originalMap -- notInterestingMap.keySet
interestingMap: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(name -> jack, hobby -> jumping)

3 ответов


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

interestingKeys.flatMap(k => originalMap.get(k).map((k, _))).toMap

это будет O(n) или O(n log m) в зависимости от вашей реализации карты (где n - размер interestingKeys и m - это размер карты), а не O(m log n) или O(mn).

если вы действительно хотите, чтобы ваш ~ оператора, вы можете использовать шаблон pimp-my-library:

class RichMap[A, B](m: Map[A, B]) {
  def ~(ks: A*) = ks.flatMap(k => m.get(k).map((k, _))).toMap
}

implicit def enrichMap[A, B](m: Map[A, B]) = new RichMap(m)

теперь originalMap ~ ("name", "hobby") возвращает Map(name -> jack, hobby -> jumping), как и следовало ожидать.


filterKeysпоможем:

scala> originalMap.filterKeys(interestingKeys.contains)
res0: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(name -> jack, hobby -> jumping)

Я думаю, что исходный код не так уж плох, и его можно легко преобразовать в однострочный, работающий на наборах ключей:

val interestingMap = originalMap -- (originalMap.keySet -- interestingKeys)

Я нахожу это вполне читаемы.