我有一个具有几个键值对的映射,并且我想要一种遍历这些对并尝试将键与另一个映射的值匹配的方法。如果存在匹配项,则值将相互替换。换句话说,如果存在匹配,则将第二张地图的匹配值替换为第一张地图的值。如果没有匹配项,则不包括在结果中。
我尝试使用scala .map函数来弄清楚逻辑,但是我对scala还是陌生的,无法完全弄清楚。
例如,我有以下两个scala Map [String,String]:
val lookupMap = Map("aaa" -> "apple", "bbb" -> "orange", "ccc" -> "banana")
val entriesMap = Map("foo" -> "ccc", "bar"-> "aaa", "baz" -> "zzz")
我想通过某种方式获得以下结果:
val result = Map("foo" -> "banana", "bar" -> "apple")
注意:不包含“ baz”,因为它与查找映射中的任何内容都不匹配。
答案 0 :(得分:4)
for
的理解可以解决这一问题。
val result = for {
(k,ev) <- entriesMap
lv <- lookupMap.get(ev)
} yield (k,lv)
//result: Map[String,String] = Map(foo -> banana, bar -> apple)
答案 1 :(得分:3)
让我们以更简单的步骤解决您的问题。
entriesMap
上不存在其值的所有对作为lookupMap
中的键。lookupMap
上的值。因此,您可以编写以下内容:
val result =
entriesMap
.filter { case (_, value) => lookupMap.contains(key = value) }
.map { case (key, value) => key -> lookupMap(value) }
但是,每次您要先filter
然后再map
时,都可以始终使用collect
(这将完成相同的工作,但仅一次迭代) 。
因此,您可以这样编写:
val result = entriesMap.collect {
case (key, value) if lookupMap.contains(key = value) => key -> lookupMap(value)
}
现在,上面代码中的一个“问题” 是,它在 Map 上使用了 unsafe apply
,如果它们的键不存在,将抛出异常。
通常,应该使用get
方法,该方法将返回包装在 Option 上的值,如果键不存在,则该值将为None
。
在这种情况下,访问并非不安全,因为我们正在检查密钥是否存在。
无论如何,人们可以将程序重新考虑为:
entriesMap
上的关联值来映射lookupMap
的值。None
的货币对,并展开Somes
。代码如下:
val result =
entriesMap
.view // Only if you are in 2.13
.mapValues(value => lookupMap.get(key = value))
.collect { case (key, Some(value)) => key -> value }
.toMap // This is necessary because mapValues returns a view, which is a lazy collection.
// Other option would have been to use just map instead of mapValues.
最后,可以直接使用来理解,而不是直接使用高阶函数。
因此,这段代码(与jwvh的答案几乎相同):
val result =
for {
(key, value) <- entriesMap // For each key-value pair in entriesMap...
newValue <- lookupMap.get(key = value) // And for each newValue associated with each original value...
} yield key -> newValue // Yield the key-newValue pair.