Scala将map [String,List [Int,Double]]转换为[Int,List [String,Double]]

时间:2014-10-16 23:01:33

标签: scala list dictionary swap

我正在努力寻找列表的特殊映射。 如果我直接向您展示具体实例,您可以更容易地理解我的问题:

如何转换

(cat, List((0, 45.42), (1, 12.45), (2, 91.45))
(dog, List((0, 23.31), (1, 10.23), (2, 52.25))

(0, List((cat, 45.42)), List((dog, 23.31))
(1, List((cat, 12.45)), List((dog, 10.23))
(2, List((cat, 91.45)), List((dog, 52.25)))

类型基本上是:

[(String, List[(Int, Double)])]

[(Int, List[(String, Double)])]

是否可以使用Scala的链式函数编程函数执行此类操作?

2 个答案:

答案 0 :(得分:1)

我不确定它是最美丽的惯用解决方案,但它有效

  val original: Map[String, List[(Int, Double)]] = Map(
    "cat" -> List((0, 45.42), (1, 12.45), (2, 91.45)),
    "dog" -> List((0, 23.31), (1, 10.23), (2, 52.25))
  )

  val flatten = for {
    (s, v) <- original
    (i, d) <- v
  } yield (i, s, d)

  implicit class RichTuple2[A, B, C](t: (A, B, C)) {
    def tail: (B, C) = (t._2, t._3)
  }

  val converted = flatten
    .groupBy(_._1)
    .mapValues(_.map(_.tail))

  println(converted)

答案 1 :(得分:1)

这是:

scala> val ori: Map[String, List[(Int, Double)]] = Map(
     |   "cat" -> List((0, 45.42), (1, 12.45), (2, 91.45)),
     |   "dog" -> List((0, 23.31), (1, 10.23), (2, 52.25))
     | )
ori: Map[String,List[(Int, Double)]] = Map(cat -> List((0,45.42), (1,12.45), (2,91.45)), dog -> List((0,23.31), (1,10.23), (2,52.25)))

scala> ori.foldLeft(Map[Int, List[(String, Double)]]()){ case (m, (k, v)) =>
     |   v.foldLeft(m){ case(r, (i, d)) => r.updated(i, r.getOrElse(i, Nil) :+ (k, d)) }
     | }
res1: scala.collection.immutable.Map[Int,List[(String, Double)]] = Map(
       0 -> List((cat,45.42), (dog,23.31)), 
       1 -> List((cat,12.45), (dog,10.23)), 
       2 -> List((cat,91.45), (dog,52.25)))