2013-04-28 32 views
9

Điều gì sẽ là một cách chức năng để nén hai từ điển trong Scala?Zip hai HashMaps (hoặc từ điển)

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

zipper(map1,map2) nên cung cấp cho một cái gì đó tương tự như

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 

Nếu không chức năng, bất kỳ phong cách khác cũng được đánh giá cao

+2

Data.Map của Haskell có một bộ kết hợp tuyệt vời được gọi là 'unionWith', điều này sẽ khiến việc này trở nên dễ dàng một cách đáng kinh ngạc. Nó và đối tác giao lộ của nó là đáng kể hữu ích, và tôi hối tiếc rằng họ chỉ có sẵn trong Scala 'IntMap' và' LongMap' (chủ yếu là vì những người được dịch từ Haskell, tôi mong đợi). – copumpkin

+0

@copumpkin: Haskell thật tuyệt vời! Tôi sẽ kiểm tra unionWith.I chỉ cần kiểm tra IntMap và nó bây giờ là superceded bởi HashMap từ 2,8 trên – RAbraham

+0

Nó không thực sự thay thế bởi 'HashMap', mặc dù những gì các tài liệu bình luận cho thấy. Chúng là các cấu trúc khác nhau và 'IntMap' có các thuộc tính khác nhau. Đôi khi bạn thực sự không muốn hàm băm trong đó, đặc biệt khi bạn muốn duy trì thứ tự dữ liệu. 'IntMap' chủ yếu có thể thực hiện' SortedMap' nhưng tôi không nghĩ nó hiện tại. Một trong số đó là nó tuân theo một thứ tự "unsigned", nhưng nó không khó để làm cho nó hoạt động như một dấu hiệu nếu đó là những gì bạn cần. – copumpkin

Trả lời

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)) 

Lưu ý sử dụng get có lẽ là thích hợp hơn để getOrElse trong trường hợp này. None được sử dụng để xác định rằng một giá trị không tồn tại thay vì sử dụng 0.

+1

mã đẹp :) – RAbraham

+0

Có cách nào để lấy 'số không' của tham số kiểu không? Dây kéo có thể được làm chung với nhau từ những pesky '0's –

+0

Tôi không chắc chắn đó là đúng hướng để khái quát, nhưng bạn có thể nhìn vào' Monoid' trong đó có một (liên kết) hoạt động và một số không. Một số không theo cách riêng của nó sẽ không có ý nghĩa nhiều, vì cái làm cho nó bằng không là cách nó tương tác với những thứ khác. Như tôi đã gợi ý trong bình luận khác của tôi, tôi nghĩ rằng 'unionWith [A, B] (x: Bản đồ [A, B], y: Bản đồ [A, B]) (f: (B, B) => B): Bản đồ [A, B] 'là cách tiếp cận lý tưởng ở đây. Hàm kết hợp chỉ được sử dụng khi có chồng chéo nên bạn thậm chí không cần một khái niệm về số không. Tổng quát hơn: 'unionWith [K, A, B, C]) (x: Bản đồ [K, A], y: Bản đồ [K, B]) (l: A => C, r: B => C, b : (A, B) => C): Bản đồ [K, C] '. –

Các vấn đề liên quan