Scala 中的多值映射
在 Scala 2.8 中,我有一个不可变映射,每个键有多个值:
Map[T,Iterable[U]]
是否有更好的表示?其次,您将如何生成这样的地图
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 等效的不可变对象?
In Scala 2.8, I have an immutable map with multiple values for each key:
Map[T,Iterable[U]]
Is there a superior representation? Secondly, how would you generate such a map from
Iterable[(T,U)]
? I am presently using:
def toGroupedMap[T,U](vals: Iterable[(T,U)]): Map[T,Iterable[U]] =
vals.groupBy(_._1).map({ case (s,it) => (s,it.map(_._2)) }).toMap
Which works, but feels clunky.
EDIT: I should specify that I am working with immutable data. Is there an immutable equivalent to MultiMap?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您真的不需要不变性,那么正如其他人所说,MultiMap 是正确的选择。如果您确实需要不变性,那么您所采取的方法就和其他方法一样简单;没有任何内置的东西(AFAIK),并且任何不可变的 MultiMap 的创建都将比您在那里的方法花费更多的工作。
表示是否优越取决于您的使用情况。您是否经常想要用一个键对应所有值来执行操作?您可以在地图中多次插入相同的值吗?如果两者都是,那么您的代表就是正确的。
如果您希望在一个键上最多插入一次相同的值,那么您应该使用
Set[U]
而不是Iterable[U]
(这可以通过添加轻松完成.toSet
为it.map(_._2)
)。如果你不喜欢处理集合/迭代并且只是忍受它(即你真的宁愿只拥有键值对而不是键集值对),那么你必须在映射周围编写一个包装类提供一个单一的映射接口,并且可以使用 +、- 和迭代器做正确的事情。
这是一个比我预期的要长一点的示例(这里格式化为剪切并粘贴到 REPL 中):
我们可以看到它按照预期工作,如下所示:(
尽管如果您想在 ++ 之后返回 MapSet ,你需要重写 ++;Map 层次结构没有自己的构建器来处理这样的事情)。
If you don't really need immutability, then as others have said,
MultiMap
is the way to go. If you do really need immutability, then the approach you've taken is as easy as anything else; there isn't anything built in (AFAIK), and any creation of a immutable MultiMap is going to take a lot more work than the method you've got there.Whether the representation is superior depends on your usage. Do you often want to do things with all values corresponding to one key? Can you insert the same value multiple times into your map? If yes to both, your representation is the right one.
If you want the same value inserted at most once at one key, then you should use
Set[U]
instead ofIterable[U]
(which can easily be done by adding.toSet
toit.map(_._2)
).If you dislike having to deal with sets/iterables and are just putting up with it (i.e. you'd really rather just have key-value pairs than key-setofvalues pairs), you'd have to write a wrapper class around the map that presents a single map interface and would do the right thing with +, -, and iterator.
Here's an example that turned out a little longer than I had anticipated (here formatted for cut and paste into the REPL):
and we can see that this works as desired like so:
(though if you wanted to get a MapSet back after ++, you'd need to override ++; the Map hierarchy doesn't have its own builders to take care of things like this).
查看 Map 的 MultiMap mix-in。
Look into the MultiMap mix-in for Map.
多重地图正是您所需要的。下面是创建一个列表,然后从列表 [(String, Int)] 向其添加条目的示例。我确信有一个更漂亮的方法。
A multimap is what you need. Here's an example of creating one and then adding entries to it from a List[(String, Int)]. I'm sure there's a prettier way.