说我有两张 Map :
val a = Map(1 -> "one", 2 -> "two", 3 -> "three")
val b = Map(1 -> "un", 2 -> "deux", 3 -> "trois")
我想通过键合并这些映射,应用一些函数来收集值(在这种特殊情况下,我想将它们收集到一个seq中,给出:
val c = Map(1 -> Seq("one", "un"), 2->Seq("two", "deux"), 3->Seq("three", "trois"))
感觉应该有一个很好的,惯用的方式来做这个 - 任何建议?如果解决方案涉及scalaz,我很高兴 .
6 回答
scala.collection.immutable.IntMap有一个
intersectionWith
方法,可以完全按照您的要求(我相信):这给你
IntMap(1 -> List(one, un), 2 -> List(two, deux), 3 -> List(three, trois))
. 请注意,它正确地忽略了仅在a
中出现的键 .作为旁注:我经常发现自己想要Scala中Haskell's Data.Map的
unionWith
,intersectionWith
等函数 . 我没有't think there'的任何原则性原因,它们只应在IntMap
上,而不是在collection.Map
基础上 .Scalaz为
A
添加了一个方法|+|
,其中Semigroup[A]
可用 .如果您映射 Map 以使每个值都是单个元素序列,那么您可以非常简单地使用它:
所以我对这两种解决方案都不太满意(我想 Build 一个新类型,所以半群并不真正感觉合适,而Infinity的解决方案看起来相当复杂),所以我暂时还没有这个 . 我很高兴看到它有所改善:
我想要在任何一个映射中都没有键时返回任何内容的行为(这与其他解决方案不同),但是指定它的方法会很好 .
在寻找其他解决方案之前,这是我的第一个方法:
为了避免碰巧只存在于a或b中的元素,过滤器很方便:
需要展平,因为b.get(x._1)返回一个选项 . 为了使展平工作,第一个元素也必须是一个选项,所以我们不能在这里使用x._2 .
对于序列,它也有效: