如何在Scala中将元组映射的映射映射为映射的元组?

4
拥有
val a: Map[String, (Int, Int)] = Map("a" -> (1, 10), "b" -> (2, 20))

在Scala中,正确的推导方式是什么?

val b: (Map[String, Int], Map[String, Int]) = (Map("a" -> 1, "b" -> 2), Map("a" -> 10, "b" -> 20))

来自 a

3个回答

13
scala> val b = (a.mapValues(_._1), a.mapValues(_._2))
b: (scala.collection.immutable.Map[String,Int], scala.collection.immutable.Map[String,Int]) = (Map(a -> 1, b -> 2),Map(a -> 10, b -> 20))

6
我喜欢Sean的答案,但如果你想出于某种原因只遍历一次地图并且不想使用Scalaz,这里有另一个解决方案:
a.foldLeft((Map.empty[String, Int], Map.empty[String, Int])) {
  case ((a1, a2), (k, (v1, v2))) => (a1 + (k -> v1), a2 + (k -> v2))
}

你有想法为什么有人会对你的建议进行负评吗? - Ivan
@Ivan 真的不知道。我有惹到某人吗? - romusz
@Ivan:我已经测试了代码 - 结果正是您指定的:(scala.collection.immutable.Map[String,Int], scala.collection.immutable.Map[String,Int]) = (Map(a -> 1, b -> 2),Map(a -> 10, b -> 20)) - romusz
我明白,但也许有些概念性的或者我们不理解的隐藏问题... 或者可能只是一个心情不好的人闲逛而已... :-) 不管怎样,感谢您的参与。 - Ivan
我也想知道。我保证会以尊严接受任何建设性的批评 ;) 感谢 Ivan 的跟进。 - romusz

2
import scalaz._
import Scalaz._

scala> val m = Map("a" -> (1, 10), "b" -> (2, 20))
m: scala.collection.immutable.Map[java.lang.String,(Int, Int)] = Map(a -> (1,10), b -> (2,20))

scala> val (a, b) = m.toSeq foldMap { case (k, (v1, v2)) => (Map(k -> v1), Map(k -> v2)) }
a: scala.collection.immutable.Map[java.lang.String,Int] = Map(b -> 2, a -> 1)
b: scala.collection.immutable.Map[java.lang.String,Int] = Map(b -> 20, a -> 10)

谢谢你。@sean-parsons的回答确实更容易读懂,但我也会尝试你的方法来检查它是否更节省内存/ CPU。而且知道这个方法也很好。 - Ivan
2
它确实更昂贵。有更多的对象创建和间接引用。Sean建议的方法既更简洁又更高效。 - missingfaktor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接