2010-09-09 28 views
6

Cách Scala ngắn gọn nhất để đảo ngược Bản đồ là gì? Bản đồ có thể chứa các giá trị không phải duy nhất.Cách Scala ngắn gọn nhất để đảo ngược Bản đồ là gì?

EDIT:

Các sự đảo ngược của Map[A, B] nên cung cấp cho Map[B, Set[A]] (hoặc một Multimap, điều đó sẽ tốt hơn).

+3

Xác định những gì là để xảy ra nếu một giá trị nhất định có mặt dưới nhiều hơn một chìa khóa. –

+0

@Randall: Xem bản chỉnh sửa. – missingfaktor

Trả lời

23

Nếu bạn có thể mất chìa khóa trùng lặp:

scala> val map = Map(1->"one", 2->"two", -2->"two") 
map: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,one), (2,two), (-2,two)) 

scala> map.map(_ swap) 
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((one,1), (two,-2)) 

Nếu bạn không muốn truy cập như một Multimap, chỉ cần một bản đồ để bộ, sau đó:

scala> map.groupBy(_._2).mapValues(_.keys.toSet) 
res1: scala.collection.immutable.Map[ 
    java.lang.String,scala.collection.immutable.Set[Int] 
] = Map((one,Set(1)), (two,Set(2, -2))) 

Nếu bạn nhấn mạnh vào nhận được một MultiMap, sau đó:

scala> import scala.collection.mutable.{HashMap, Set, MultiMap} 
scala> ((new HashMap[String,Set[Int]] with MultiMap[String,Int]) ++= 
    |   map.groupBy(_._2).mapValues(Set[Int]() ++= _.keys)) 
res2: scala.collection.mutable.HashMap[String,scala.collection.mutable.Set[Int]] 
with scala.collection.mutable.MultiMap[String,Int] = Map((one,Set(1)), (two,Set(-2, 2))) 
+0

+1 cho tính ngắn gọn và giới thiệu cho tôi về bản đồValues ​​:-) –

+0

một khởi đầu tốt hơn sẽ rõ ràng hơn, ví dụ: Bản đồ (1 -> "một", 2 -> "hai", 3 -> "hai", 4 -> "hai") –

+0

@Rodney - Được rồi, được rồi, tôi sẽ hiển thị trường hợp trùng lặp! –

4
scala> val m1 = Map(1 -> "one", 2 -> "two", 3 -> "three", 4 -> "four") 
m1: scala.collection.immutable.Map[Int,java.lang.String] = Map((1,one), (2,two), (3,three), (4,four)) 

scala> m1.map(pair => pair._2 -> pair._1) 
res0: scala.collection.immutable.Map[java.lang.String,Int] = Map((one,1), (two,2), (three,3), (four,4)) 

Chỉnh sửa cho câu hỏi được làm rõ:

object RevMap { 
    def 
    main(args: Array[String]): Unit = { 
    val m1 = Map("one" -> 3, "two" -> 3, "three" -> 5, "four" -> 4, "five" -> 5, "six" -> 3) 

    val rm1 = (Map[Int, Set[String]]() /: m1) { (map: Map[Int, Set[String]], pair: (String, Int)) => 
               map + ((pair._2, map.getOrElse(pair._2, Set[String]()) + pair._1)) } 

    printf("m1=%s%nrm1=%s%n", m1, rm1) 
    } 
} 

% scala RevMap 
m1=Map(four -> 4, three -> 5, two -> 3, six -> 3, five -> 4, one -> 3) 
rm1=Map(4 -> Set(four, five), 5 -> Set(three), 3 -> Set(two, six, one)) 

Tôi không chắc chắn điều này đủ điều kiện gọn gàng.

+1

+1 cho giải pháp làm việc. :-) – missingfaktor

0

Làm thế nào về:

implicit class RichMap[A, B](map: Map[A, Seq[B]]) 
    { 
    import scala.collection.mutable._ 

    def reverse: MultiMap[B, A] = 
    { 
     val result = new HashMap[B, Set[A]] with MultiMap[B, A] 

     map.foreach(kv => kv._2.foreach(result.addBinding(_, kv._1))) 

     result 
    } 
    } 

hoặc

implicit class RichMap[A, B](map: Map[A, Seq[B]]) 
    { 
    import scala.collection.mutable._ 

    def reverse: MultiMap[B, A] = 
    { 
     val result = new HashMap[B, Set[A]] with MultiMap[B, A] 

     map.foreach{case(k,v) => v.foreach(result.addBinding(_, k))} 

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