Ale*_*yMK 95 scala scala-collections
学习Scala当前需要反转Map来进行一些反向值 - >键查找.我正在寻找一种简单的方法来做到这一点,但只提出:
(Map() ++ origMap.map(kvp=>(kvp._2->kvp._1)))
Run Code Online (Sandbox Code Playgroud)
有人有更优雅的方法吗?
Dan*_*ral 166
假设值是唯一的,这适用:
(Map() ++ origMap.map(_.swap))
Run Code Online (Sandbox Code Playgroud)
但是,在Scala 2.8上,它更容易:
origMap.map(_.swap)
Run Code Online (Sandbox Code Playgroud)
能够做到这一点是Scala 2.8有一个新的集合库的部分原因.
Rok*_*alj 44
在数学上,映射可能不是可逆的(单射),例如,Map[A,B]
你不能得到Map[B,A]
,而是得到Map[B,Set[A]]
,因为可能存在与相同值相关联的不同键.所以,如果你有兴趣知道所有的密钥,这里是代码:
scala> val m = Map(1 -> "a", 2 -> "b", 4 -> "b")
scala> m.groupBy(_._2).mapValues(_.keys)
res0: Map[String,Iterable[Int]] = Map(b -> Set(2, 4), a -> Set(1))
Run Code Online (Sandbox Code Playgroud)
Lee*_*oll 10
你可以在几个方面进行迭代时避免使用._1的东西.
这是一种方式.这使用了一个部分函数,它涵盖了对地图重要的唯一一个案例:
Map() ++ (origMap map {case (k,v) => (v,k)})
Run Code Online (Sandbox Code Playgroud)
这是另一种方式:
import Function.tupled
Map() ++ (origMap map tupled {(k,v) => (v,k)})
Run Code Online (Sandbox Code Playgroud)
map迭代使用两个元素元组调用一个函数,而匿名函数需要两个参数.Function.tupled进行翻译.
我来到这里寻找一种方法将Map [A,Seq [B]]类型的Map反转为Map [B,Seq [A]],其中新地图中的每个B都与旧地图中的每个A相关联.其中B包含在A的相关序列中.
例如,
Map(1 -> Seq("a", "b"), 2-> Seq("b", "c"))
将转换为
Map("a" -> Seq(1), "b" -> Seq(1, 2), "c" -> Seq(2))
这是我的解决方案:
val newMap = oldMap.foldLeft(Map[B, Seq[A]]().withDefaultValue(Seq())) {
case (m, (a, bs)) => bs.foldLeft(m)((map, b) => map.updated(b, m(b) :+ a))
}
Run Code Online (Sandbox Code Playgroud)
其中oldMap的类型Map[A, Seq[B]]
和newMap的类型Map[B, Seq[A]]
嵌套的foldLefts让我有点畏缩,但这是我能找到的最简单的方法来实现这种类型的反转.有人有更清洁的解决方案?
好的,这是一个非常老的问题,有很多好的答案,但是我已经制造了终极的,万事俱备的Swiss-Army刀,Map
逆变器,并且可以在此发布它。
实际上是两个逆变器。一个用于单个价值要素...
//from Map[K,V] to Map[V,Set[K]], traverse the input only once
implicit class MapInverterA[K,V](m :Map[K,V]) {
def invert :Map[V,Set[K]] =
m.foldLeft(Map.empty[V, Set[K]]) {
case (acc,(k, v)) => acc + (v -> (acc.getOrElse(v,Set()) + k))
}
}
Run Code Online (Sandbox Code Playgroud)
...和另一个非常相似的价值收集。
import scala.collection.generic.CanBuildFrom
import scala.collection.mutable.Builder
import scala.language.higherKinds
//from Map[K,C[V]] to Map[V,C[K]], traverse the input only once
implicit class MapInverterB[K,V,C[_]](m :Map[K,C[V]]
)(implicit ev :C[V] => TraversableOnce[V]) {
def invert(implicit bf :CanBuildFrom[Nothing,K,C[K]]) :Map[V,C[K]] =
m.foldLeft(Map.empty[V, Builder[K,C[K]]]) {
case (acc, (k, vs)) =>
vs.foldLeft(acc) {
case (a, v) => a + (v -> (a.getOrElse(v,bf()) += k))
}
}.mapValues(_.result())
}
Run Code Online (Sandbox Code Playgroud)
用法:
Map(2 -> Array('g','h'), 5 -> Array('g','y')).invert
//res0: Map(g -> Array(2, 5), h -> Array(2), y -> Array(5))
Map('q' -> 1.1F, 'b' -> 2.1F, 'c' -> 1.1F, 'g' -> 3F).invert
//res1: Map(1.1 -> Set(q, c), 2.1 -> Set(b), 3.0 -> Set(g))
Map(9 -> "this", 8 -> "that", 3 -> "thus", 2 -> "thus").invert
//res2: Map(this -> Set(9), that -> Set(8), thus -> Set(3, 2))
Map(1L -> Iterator(3,2), 5L -> Iterator(7,8,3)).invert
//res3: Map(3 -> Iterator(1, 5), 2 -> Iterator(1), 7 -> Iterator(5), 8 -> Iterator(5))
Map.empty[Unit,Boolean].invert
//res4: Map[Boolean,Set[Unit]] = Map()
Run Code Online (Sandbox Code Playgroud)
我希望将这两种方法都放在同一个隐式类中,但是花在我身上的时间越多,它看起来就越有问题。
归档时间: |
|
查看次数: |
25787 次 |
最近记录: |