scala 按键集过滤地图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9031023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:49:45  来源:igfitidea点击:

Filter Map by key set

scala

提问by Timo Westk?mper

Is there a shortcut to filter a Map keeping only the entries where the key is contained in a given Set?

是否有过滤 Map 的快捷方式,仅保留给定 Set 中包含键的条目?

Here is some example code

这是一些示例代码

scala> val map = Map("1"->1, "2"->2, "3"->3)
map: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1, 2 -> 2, 3 -> 3)

scala> map.filterKeys(Set("1","2").contains)
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1, 2 -> 2)

I am searching for something shorter than this.

我正在寻找比这更短的东西。

回答by oxbow_lakes

Answering the Question

回答问题

You can take advantage of the fact that a Set[A]is a predicate; i.e. A => Boolean

您可以利用 aSet[A]是谓词这一事实;IEA => Boolean

map filterKeys set

Here it is at work:

这是在工作:

scala> val map = Map("1" -> 1, "2" -> 2, "3" -> 3)
map: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1, 2 -> 2, 3 -> 3)

scala> val set = Set("1", "2")
set: scala.collection.immutable.Set[java.lang.String] = Set(1, 2)

scala> map filterKeys set
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1, 2 -> 2)

Or if you prefer:

或者,如果您更喜欢:

scala> map filterKeys Set("1", "2")
res1: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1, 2 -> 2)


Predicates

谓词

It's actually really useful to have some wrapper around a predicate. Like so:

对谓词进行一些包装实际上非常有用。像这样:

scala> class PredicateW[A](self: A => Boolean) {
   | def and(other: A => Boolean): A => Boolean = a => self(a) && other(a)
   | def or(other: A => Boolean): A => Boolean = a => self(a) || other(a)
   | def unary_! : A => Boolean = a => !self(a)
   | }
defined class PredicateW

And an implicit conversion:

还有一个隐式转换:

scala> implicit def Predicate_Is_PredicateW[A](p: A => Boolean) = new PredicateW(p)
Predicate_Is_PredicateW: [A](p: A => Boolean)PredicateW[A]

And then you can use it:

然后你可以使用它:

scala> map filterKeys (Set("1", "2") and Set("2", "3"))
res2: scala.collection.immutable.Map[java.lang.String,Int] = Map(2 -> 2)

scala> map filterKeys (Set("1", "2") or Set("2", "3"))
res3: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1, 2 -> 2, 3 -> 3)

scala> map filterKeys !Set("2", "3")
res4: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1)

This can be extended to xor, nandetc etc and if you include symbolic unicode can make for amazingly readable code:

这可以扩展到xornand等等,如果你包含符号 unicode 可以使代码变得非常可读:

val mustReport = trades filter (uncoveredShort ∨ exceedsDollarMax)

val european = { 
  val Europe = (_ : Market).exchange.country.region == Region.EU
  trades filter (_.market ∈: Europe)
}

回答by missingfaktor

A tangential tip, in case you are going to follow the PredicateWidea in @oxbow_lakes' answer:

切线提示,以防您要遵循PredicateW@oxbow_lakes 回答中的想法:

In functional programming, instead of defining ad hoc functions, we aim for more generalized and composable abstractions. For this particular case, Applicativefits the bill.

在函数式编程中,我们的目标不是定义临时函数,而是更通用和可组合的抽象。对于这种特殊情况,Applicative符合要求。

Setthemselves are functions, and the Applicativeinstance for [B]Function1[A, B]lets us lift functions to context. In other words, you can lift functions of type (Boolean, Boolean) => Boolean(such as ||, &&etc.) to (A => Boolean, A => Boolean) => (A => Boolean). (Hereyou can find a great explanation on this concept of lifting.)

Set它们本身就是函数,而Applicativefor的实例[B]Function1[A, B]让我们将函数提升到上下文中。换句话说,可以解除类型的功能(Boolean, Boolean) => Boolean(例如||&&等)(A => Boolean, A => Boolean) => (A => Boolean)。(在这里你可以找到关于这个提升概念的很好的解释。)

However the data structure Setitself has an Applicativeinstance available, which will be favored over [B]Applicative[A => B]instance. To prevent that, we will have to explicitly tell the compiler to treat the given set as a function. We define a following enrichment for that:

然而,数据结构Set本身有一个Applicative可用的实例,这将比[B]Applicative[A => B]实例更受青睐。为了防止这种情况,我们必须明确告诉编译器将给定的集合视为一个函数。我们为此定义了以下丰富内容:

scala> implicit def setAsFunction[A](set: Set[A]) = new {
     |   def f: A => Boolean = set
     | }
setAsFunction: [A](set: Set[A])java.lang.Object{def f: A => Boolean}

scala> Set(3, 4, 2).f
res144: Int => Boolean = Set(3, 4, 2)

And now put this Applicativegoodness into use.

现在把这个Applicative好处投入使用。

scala> val map = Map("1" -> 1, "2" -> 2, "3" -> 3)
map: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1, 2 -> 2, 3 -> 3)

scala> map filterKeys ((Set("1", "2").f |@| Set("2", "3").f)(_ && _))
res150: scala.collection.immutable.Map[java.lang.String,Int] = Map(2 -> 2)

scala> map filterKeys ((Set("1", "2").f |@| Set("2", "3").f)(_ || _))
res151: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1, 2 -> 2, 3 -> 3)

scala> map filterKeys (Set("2", "3").f map (!_))
res152: scala.collection.immutable.Map[java.lang.String,Int] = Map(1 -> 1)

Note: All of the above requires Scalaz.

注意:以上所有内容都需要 Scalaz。

回答by Jesper

Sorry, not a direct answer to your question, but if you know which keys you want to remove (instead of which ones you want to keep), you could do this:

抱歉,不是直接回答您的问题,但如果您知道要删除哪些键(而不是要保留哪些键),您可以这样做:

map -- Set("3")