过滤Scala Multimap并输出为元组列表

时间:2012-07-22 10:39:23

标签: scala functional-programming tuples multimap

我有一张使用multimap特征的地图,就像这样 val multiMap = new HashMap[Foo, Set[Bar]] with MultiMap[Foo, Bar]
我想结合在特定值上过滤这个地图 multiMap.values.filter(bar => barCondition)
将匹配结果展平为形式的元组列表
val fooBarPairs: List[(Foo, Bar)]
这样做的惯用方法是什么?我希望Scala可以在不循环的情况下提供类似于变形的东西,但作为一个完整的新手,我不确定我的选择是什么。

3 个答案:

答案 0 :(得分:4)

以下是一个例子:

import collection.mutable.{HashMap, MultiMap, Set}

val mm = new HashMap[String, Set[Int]] with MultiMap[String, Int]
mm.addBinding("One", 1).addBinding("One",11).addBinding("Two",22).
  addBinding("Two",222)
  // mm.type = Map(Two -> Set(22, 222), One -> Set(1, 11))

我认为获得所需内容的最简单方法是使用for-expression:

for {
  (str, xs) <- mm.toSeq
  x         <- xs
  if x > 10
} yield (str, x)      // = ArrayBuffer((Two,222), (Two,22), (One,11))

您需要.toSeq或输出类型为Map,这意味着后续元素会覆盖每个映射。如果您需要toList专门用于此输出,请使用List

答案 1 :(得分:1)

以下是我认为你想要做的一个例子:

scala> mm
res21: scala.collection.mutable.HashMap[String,scala.collection.mutable.Set[Int]] with scala.collection.mutable.MultiMap[String,Int]
= Map(two -> Set(6, 4, 5), one -> Set(2, 1, 3))

scala> mm.toList.flatMap(pair =>
         pair._2.toList.flatMap(bar =>
           if (bar%2==0)
             Some((pair._1, bar))
           else
             None))

res22: List[(String, Int)] = List((two,6), (two,4), (one,2))

答案 2 :(得分:1)

这是另一个更简洁的解决方案:

import collection.mutable.{HashMap, MultiMap, Set}

val mm = new HashMap[String, Set[Int]] with MultiMap[String, Int]
val f = (i: Int) => i > 10

mm.addBinding("One", 1)
  .addBinding("One",11)
  .addBinding("Two",22)
  .addBinding("Two",222)
  /* Map(Two -> Set(22, 222), One -> Set(1, 11)) */

mm.map{case (k, vs) => vs.filter(f).map((k, _))}.flatten
  /* ArrayBuffer((Two,222), (Two,22), (One,11)) */