从Scala中的Seq of Map创建所有键的并集的功能方法

时间:2014-04-20 20:13:18

标签: scala collections

我是地图序列

 Seq[Map[String,Int]] 

我想创建一个Seq / Set,它是每个Map中所有键的Union。

unionallkeys = ( "a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3" ) 

在下面的示例中。

scala> val a = Map( ("a1", 1), ("a2", 2), ("a3", 3) ) 
a: scala.collection.immutable.Map[String,Int] = Map(a1 -> 1, a2 -> 2, a3 -> 3)

scala> val b = Map( ("b1", 1), ("b2", 2), ("b3", 3) ) 
b: scala.collection.immutable.Map[String,Int] = Map(b1 -> 1, b2 -> 2, b3 -> 3)

scala> val c = Map( ("c1", 1), ("c2", 2), ("c3", 3) ) 
c: scala.collection.immutable.Map[String,Int] = Map(c1 -> 1, c2 -> 2, c3 -> 3)

scala> val misc = Map( ("a1", 1), ("b2", 2), ("c3", 3) )
misc: scala.collection.immutable.Map[String,Int] = Map(a1 -> 1, b2 -> 2, c3 -> 3)
                             ^

scala> val rows = List(a,b,c,misc)
rows: List[scala.collection.immutable.Map[String,Int]] = List(Map(a1 -> 1, a2 -> 2, a3 -> 3), Map(b1 -> 1, b2 -> 2, b3 -> 3), Map(c1 -> 1, c2 -> 2, c3 -> 3), Map(a1 -> 1, b2 -> 2, c3 -> 3))

2 个答案:

答案 0 :(得分:7)

你可以把它写成一个相当清晰的单行词:

scala> val keys: Set[String] = rows.flatMap(_.keySet).toSet
keys: Set[String] = Set(c3, b2, b3, c2, b1, c1, a3, a1, a2)

让我们一步一步地解决这个问题。首先,地图上的keySet方法会为您提供一组地图键。如果你想要一组键列表,你可以写下以下内容:

scala> val keySets: List[Set[String]] = rows.map(_.keySet)
keySets: List[Set[String]] = List(Set(a1, a2, a3), Set(b1, b2, b3), ...

然后你可以展平嵌套结构:

scala> val keyList: List[String] = keySets.flatten
keyList: List[String] = List(a1, a2, a3, b1, b2, b3, c1, c2, c3, a1, b2, c3)

请注意,结果具有外部集合的类型 - 即。它是一个列表,而不是一个集合。您可以将其转换为toSet

的集合
scala> val keys: Set[String] = keyList.toSet
keys: Set[String] = Set(c3, b2, b3, c2, b1, c1, a3, a1, a2)

你已经完成了。上面的第一行只是一次完成所有这些步骤,并将mapflatten次调用合并为一个flatMap

答案 1 :(得分:0)

Travis solution是不可变的,在设计方面更好。

让我提供一个使用可变集合的解决方案:

def keysUnion[A,B](maps: Seq[Map[A,B]]): scala.collection.Set[A] = {
  val allKeys = scala.collection.mutable.Set[A]()
  maps.foreach( m => allKeys ++= m.keySet )
  allKeys
}


// test with some random input data
import scala.util.Random
val maps = (1 to 10).map( i => (1 to i).map( k => k -> k ).toMap )

keysUnion(maps)

我不知道mutable.Set是否有效。而且很可能不可变解决方案的.toSet也是如此。因此,对于简单的情况,它应该非常相似,但如果平坦的键列表(实际上)很大,它应该会更好。

注意:的 当使用可变集合时,最好将其隐藏在输出具有不可变API的特征的方法中。这就是为什么我提供的解决方案是以输出scala.collection.Set的函数的形式。