Scala 中具有多个值的可变映射
Mutable map with multiple values in Scala
我想要一张地图,以便:
- 我可以更新它 -> 可变
- 我可以有多个值 -> old multi map
即我需要一个形式的集合:
k1 -> v1, k1 -> v2, ..., k2 -> v1, k2 -> v2, k2 -> v3 等
归根结底,我需要收集所有这些信息:
k1 -> Seq(v1,v2), ..., k2 -> Seq(v1,v2,v3)
我如何在 Scala 中执行此操作?
编辑
我在 Scastie 试过这个:
val m = new scala.collection.mutable.Map[Int,Int] with scala.collection.mutable.MultiMap[Int,Int]
m += (1 -> 2)
m += (1 -> 3)
m
但我得到:
illegal inheritance;
<$anon: Int => Int with Int => scala.collection.mutable.Set[Int]> inherits different type instances of trait Map:
scala.collection.mutable.Map[Int,scala.collection.mutable.Set[Int]] and scala.collection.mutable.Map[Int,Int]
trait MultiMap in package mutable is deprecated (since 2.13.0): Use a scala.collection.mutable.MultiDict in the scala-collection-contrib module
正如在评论部分讨论的那样,您可以继续 MultiDict
from scala-collection-contrlib
库。示例:
import scala.collection.mutable
def convert[K, V](iterable: Iterable[(K, V)]): mutable.MultiDict[K, V] = {
iterable.foldLeft(mutable.MultiDict.empty[K, V])(_ addOne _)
}
val list = List("k1" -> "v1", "k1" -> "v2", "k1" -> "v3", "k2" -> "v1", "k3" -> "v1")
val map = convert(list)
println(map.sets)
将打印:HashMap(k1 -> HashSet(v1, v2, v3), k2 -> HashSet(v1), k3 -> HashSet(v1))
当人们说“避免在 scala 中使用可变结构”时,它特别适用于那些必须询问有关如何创建多图的问题的人。
我的意思是,这真的不是火箭科学:
val foo = mutable.Map[Int, List[Int]]().withDefault(_ => Nil)
foo += 1 -> (1::foo(1))
foo += 1 -> (2::foo(1))
foo += 1 -> foo(1).filterNot(Set)
foo += 1 -> foo(1).tail
tuples.foreach { case (k,v) => foo += k -> (v::foo(k)) }
//etc.
但是如果你不得不问如何做到这一点,你很可能最终会错误地使用它(使用可变结构很容易)。我强烈建议您坚持使用不可变集合(并避免一般情况下的可变状态),直到您对语言有足够的掌握,能够明确识别可变实际上是正确解决方案的情况。
我想要一张地图,以便:
- 我可以更新它 -> 可变
- 我可以有多个值 -> old multi map
即我需要一个形式的集合:
k1 -> v1, k1 -> v2, ..., k2 -> v1, k2 -> v2, k2 -> v3 等
归根结底,我需要收集所有这些信息:
k1 -> Seq(v1,v2), ..., k2 -> Seq(v1,v2,v3)
我如何在 Scala 中执行此操作?
编辑
我在 Scastie 试过这个:
val m = new scala.collection.mutable.Map[Int,Int] with scala.collection.mutable.MultiMap[Int,Int]
m += (1 -> 2)
m += (1 -> 3)
m
但我得到:
illegal inheritance;
<$anon: Int => Int with Int => scala.collection.mutable.Set[Int]> inherits different type instances of trait Map:
scala.collection.mutable.Map[Int,scala.collection.mutable.Set[Int]] and scala.collection.mutable.Map[Int,Int]
trait MultiMap in package mutable is deprecated (since 2.13.0): Use a scala.collection.mutable.MultiDict in the scala-collection-contrib module
正如在评论部分讨论的那样,您可以继续 MultiDict
from scala-collection-contrlib
库。示例:
import scala.collection.mutable
def convert[K, V](iterable: Iterable[(K, V)]): mutable.MultiDict[K, V] = {
iterable.foldLeft(mutable.MultiDict.empty[K, V])(_ addOne _)
}
val list = List("k1" -> "v1", "k1" -> "v2", "k1" -> "v3", "k2" -> "v1", "k3" -> "v1")
val map = convert(list)
println(map.sets)
将打印:HashMap(k1 -> HashSet(v1, v2, v3), k2 -> HashSet(v1), k3 -> HashSet(v1))
当人们说“避免在 scala 中使用可变结构”时,它特别适用于那些必须询问有关如何创建多图的问题的人。 我的意思是,这真的不是火箭科学:
val foo = mutable.Map[Int, List[Int]]().withDefault(_ => Nil)
foo += 1 -> (1::foo(1))
foo += 1 -> (2::foo(1))
foo += 1 -> foo(1).filterNot(Set)
foo += 1 -> foo(1).tail
tuples.foreach { case (k,v) => foo += k -> (v::foo(k)) }
//etc.
但是如果你不得不问如何做到这一点,你很可能最终会错误地使用它(使用可变结构很容易)。我强烈建议您坚持使用不可变集合(并避免一般情况下的可变状态),直到您对语言有足够的掌握,能够明确识别可变实际上是正确解决方案的情况。