2013-04-28 47 views
9

什麼是在Scala中壓縮兩個字典的功能方式?Zip 2 HashMap(或字典)

map1 = new HashMap("A"->1,"B"->2) 
map2 = new HashMap("B"->22,"D"->4) // B is the only common key 

zipper(map1,map2)應該給類似的東西來

Seq(("A",1,0), // no A in second map, so third value is zero 
     ("B",2,22), 
     ("D",0,4)) // no D in first map, so second value is zero 

如果沒有的功能,任何其他樣式也可以理解使用get

+2

Haskell的Data.Map有一個美妙的combinator,名爲'unionWith',它可以使這非常簡單。它和它的交集對應是非常有用的,我很遺憾他們只能在Scala的'IntMap'和'LongMap'中使用(主要是因爲那些從Haskell翻譯過,我期望)。 – copumpkin 2013-04-28 00:32:26

+0

@copumpkin:哈斯克爾太棒了!我會檢查出unionWith.I只是檢查了IntMap,它現在被HashMap從2.8773替換爲 – RAbraham 2013-04-28 00:36:53

+0

。儘管文檔註釋的含義,它並沒有被'HashMap'所取代。它們是不同的結構,'IntMap'具有不同的屬性。有時你真的不希望哈希函數在那裏,特別是當你想維護數據的順序時。 'IntMap'大多可以實現'SortedMap',但我認爲它現在不行。一個問題是,它遵循一個「無符號」的順序,但如果這是你所需要的,就不難使其表現得像一個簽名的那樣。 – copumpkin 2013-04-28 01:58:56

回答

13
def zipper(map1: Map[String, Int], map2: Map[String, Int]) = { 
    for(key <- map1.keys ++ map2.keys) 
    yield (key, map1.getOrElse(key, 0), map2.getOrElse(key, 0)) 
} 


scala> val map1 = scala.collection.immutable.HashMap("A" -> 1, "B" -> 2) 
map1: scala.collection.immutable.HashMap[String,Int] = Map(A -> 1, B -> 2) 

scala> val map2 = scala.collection.immutable.HashMap("B" -> 22, "D" -> 4) 
map2: scala.collection.immutable.HashMap[String,Int] = Map(B -> 22, D -> 4) 

scala> :load Zipper.scala 
Loading Zipper.scala... 
zipper: (map1: Map[String,Int], map2: Map[String,Int])Iterable[(String, Int, Int)] 

scala> zipper(map1, map2) 
res1: Iterable[(String, Int, Int)] = Set((A,1,0), (B,2,22), (D,0,4)) 

注可能是最好getOrElse在這種情況下。 None用於指定值不存在,而不是使用0

+1

美麗的代碼:) – RAbraham 2013-04-28 00:45:16

+0

是否有某種方式來獲得類型參數的「零」?拉鍊可以通用,除了那些討厭的'0's – 2013-04-28 07:32:16

+0

我不確定這是否是正確的方向來推廣,但你可以看看'Monoid',它有一個(關聯)操作和一個零。零點本身沒有多大意義,因爲它使零點與其他事物相互作用的方式是零。正如我在其他評論中所說的,我認爲'unionWith [A,B](x:Map [A​​,B],y:Map [A​​,B])(f:(B,B)=> B) [A,B]'是理想的方法。只有在重疊時才使用組合函數,因此您甚至不需要零的概念。更一般的:'unionWith [K,A,B,C])(x:Map [K,A],y:Map [K,B])(l:A => C,r:B => C,b :(A,B)=> C):映射[K,C]'。 – 2013-04-28 15:10:17