Карта только с определенными ключами
что касается карт в 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)
Я нахожу это вполне читаемы.