gpt4 book ai didi

scala - Scala 中的多值映射

转载 作者:行者123 更新时间:2023-12-04 18:53:44 26 4
gpt4 key购买 nike

在 Scala 2.8 中,我有一个不可变的映射,每个键都有多个值:

Map[T,Iterable[U]]

有上级代表吗?其次,你将如何生成这样的 map
Iterable[(T,U)]

?我目前正在使用:
def toGroupedMap[T,U](vals: Iterable[(T,U)]): Map[T,Iterable[U]] =
vals.groupBy(_._1).map({ case (s,it) => (s,it.map(_._2)) }).toMap

哪个有效,但感觉很笨重。

编辑:我应该指定我正在处理不可变数据。是否有一个不可变的等价于 MultiMap?

最佳答案

如果你真的不需要不变性,那么正如其他人所说,MultiMap是要走的路。如果您确实需要不变性,那么您采用的方法与其他任何方法一样简单;没有任何内置(AFAIK),并且任何不可变 MultiMap 的创建都将比您在那里获得的方法花费更多的工作。

表示是否优越取决于您的使用情况。你是否经常想把所有的值都对应一个键来做事?您可以在 map 中多次插入相同的值吗?如果两者都是肯定的,那么您的代表就是正确的。

如果您希望一个键最多插入一次相同的值,那么您应该使用 Set[U]而不是 Iterable[U] (这可以通过将 .toSet 添加到 it.map(_._2) 来轻松完成)。

如果您不喜欢处理集合/可迭代对象并且只是忍受它(即您真的宁愿只有键值对而不是键值对),则必须围绕映射编写一个包装类呈现一个单一的 map 界面,并会用 +、- 和迭代器做正确的事情。

这是一个比我预期的要长一点的例子(这里格式化为剪切和粘贴到 REPL 中):

import scala.collection._
class MapSet[A,B](
val sets: Map[A,Set[B]] = Map[A,Set[B]]()
) extends Map[A,B] with MapLike[A,B,MapSet[A,B]] {
def get(key: A) = sets.getOrElse(key,Set[B]()).headOption
def iterator = new Iterator[(A,B)] {
private val seti = sets.iterator
private var thiskey:Option[A] = None
private var singles:Iterator[B] = Nil.iterator
private def readyNext {
while (seti.hasNext && !singles.hasNext) {
val kv = seti.next
thiskey = Some(kv._1)
singles = kv._2.iterator
}
}
def hasNext = {
if (singles.hasNext) true
else {
readyNext
singles.hasNext
}
}
def next = {
if (singles.hasNext) (thiskey.get , singles.next)
else {
readyNext
(thiskey.get , singles.next)
}
}
}
def +[B1 >: B](kv: (A,B1)):MapSet[A,B] = {
val value:B = kv._2.asInstanceOf[B]
new MapSet( sets + ((kv._1 , sets.getOrElse(kv._1,Set[B]()) + value)) )
}
def -(key: A):MapSet[A,B] = new MapSet( sets - key )
def -(kv: (A,B)):MapSet[A,B] = {
val got = sets.get(kv._1)
if (got.isEmpty || !got.get.contains(kv._2)) this
else new MapSet( sets + ((kv._1 , got.get - kv._2)) )
}
override def empty = new MapSet( Map[A,Set[B]]() )
}

我们可以看到这按预期工作,如下所示:
scala> new MapSet() ++ List(1->"Hi",2->"there",1->"Hello",3->"Bye")
res0: scala.collection.Map[Int,java.lang.String] = Map(1 -> Hi, 1 -> Hello, 2 -> there, 3 -> Bye)

scala> res0 + (2->"ya")
res1: scala.collection.Map[Int,java.lang.String] = Map(1 -> Hi, 1 -> Hello, 2 -> there, 2 -> ya, 3 -> Bye)

scala> res1 - 1
res2: scala.collection.Map[Int,java.lang.String] = Map(2 -> there, 2 -> ya, 3 -> Bye)

(尽管如果您想在++ 之后取回 MapSet,则需要覆盖++;Map 层次结构没有自己的构建器来处理此类事情)。

关于scala - Scala 中的多值映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2193708/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com