Scala 的 Map.unzip 返回的原因(可迭代,可迭代)
有一天,我想知道为什么 scala.collection.Map 将其 unzip 方法定义为
def unzip [A1, A2] (implicit asPair: ((A, B)) ⇒ (A1, A2)): (Iterable[A1], Iterable[A2])
由于该方法“仅”返回一对 Iterable 而不是一对 Seq,因此不能保证原始映射中的键/值对出现在匹配返回序列中的索引,因为 Iterable 不保证遍历的顺序。因此,如果我有一个
Map((1,A), (2,B))
,那么在调用之后,
Map((1,A), (2,B)) unzip
我可能会得到
... = (List(1, 2),List(A, B))
同样的
... = (List(2, 1),List(B, A))
结果。虽然我可以想象这背后与存储相关的原因(例如,考虑 HashMap),但我想知道你们对这种行为有何看法。对于 Map.unzip 方法的用户来说,这些项目可能会以相同的配对顺序返回(我敢打赌这可能几乎总是如此),但因为不能保证这可能会反过来产生难以发现的错误图书馆用户的代码。
也许这种行为应该在随附的 scaladoc 中更明确地表达?
编辑:请注意,我并不是将地图称为有序集合。我只对解压后的“匹配”序列感兴趣,即因为
val (keys, values) = someMap.unzip
它适用于所有我(keys(i), value(i)) 是原始映射的元素。
the other day I was wondering why scala.collection.Map defines its unzip method as
def unzip [A1, A2] (implicit asPair: ((A, B)) ⇒ (A1, A2)): (Iterable[A1], Iterable[A2])
Since the method returns "only" a pair of Iterable instead of a pair of Seq it is not guaranteed that the key/value pairs in the original map occur at matching indices in the returned sequences since Iterable doesn't guarantee the order of traversal. So if I had a
Map((1,A), (2,B))
, then after calling
Map((1,A), (2,B)) unzip
I might end up with
... = (List(1, 2),List(A, B))
just as well as with
... = (List(2, 1),List(B, A))
While I can imagine storage-related reasons behind this (think of HashMaps, for example) I wonder what you guys think about this behavior. It might appear to users of the Map.unzip method that the items were returned in the same pair order (and I bet this is probably almost always the case) yet since there's no guarantee this might in turn yield hard-to-find bugs in the library user's code.
Maybe that behavior should be expressed more explicitly in the accompanying scaladoc?
EDIT: Please note that I'm not referring to maps as ordered collections. I'm only interested in "matching" sequences after unzip, i.e. for
val (keys, values) = someMap.unzip
it holds for all i that (keys(i), values(i)) is an element of the original mapping.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果你展开
unzip
的描述,你会得到答案:换句话说,它并没有专门用于
Map
。不过,你的论点是合理的,我敢说,如果你用你的推理开一张增强票,你可能会如愿以偿。特别是如果您继续制作补丁——如果不出意外,至少您会在这样做时学到更多关于 Scala 集合的知识。
If you expand
unzip
's description, you'll get the answer:In other words, it didn't get specialized for
Map
.Your argument is sound, though, and I daresay you might get your wishes if you open an enhancement ticket with your reasoning. Specially if you go ahead an produce a patch as well -- if nothing else, at least you'll learn a lot more about Scala collections in doing so.
其实你举的例子是不会出现的。
Map
将始终以成对的方式解压缩。您关于Iterable
不保证排序的说法并不完全正确。更准确地说,任何给定的 Iterable 不必保证顺序,但这取决于实现。在 Map.unzip 的情况下,不能保证对的顺序,但对中的项目不会改变它们的匹配方式——匹配是的基本属性地图
。您可以阅读 源代码到GenericTraversableTemplate
来验证情况是否如此。Actually, the examples you gave will not occur. The
Map
will always be unzipped in a pair-wise fashion. Your statement thatIterable
does not guarantee the ordering, is not entirely true. It is more accurate to say that any givenIterable
does not have to guarantee the ordering, but this is dependent on implementation. In the case ofMap.unzip
, the ordering of pairs is not guaranteed, but items in the pairs will not change they way they are matched up -- that matching is a fundamental property of theMap
. You can read the source toGenericTraversableTemplate
to verify this is the case.一般来说,地图没有自然序列:它们是无序的集合。您的键碰巧具有自然顺序这一事实并不会改变一般情况。
(但是我无法解释为什么 Map 有一个 zipWithIndex 方法。这为我的观点提供了一个反驳。我猜它的存在是为了与其他集合保持一致,尽管它提供了索引,不保证它们在后续调用中相同。)
Maps, generally, do not have a natural sequence: they are unordered collections. The fact your keys happen to have a natural order does not change the general case.
(However I am at a loss to explain why Map has a
zipWithIndex
method. This provides a counter-argument to my point. I guess it is there for consistency with other collections and that, although it provides indices, they are not guaranteed to be the same on subsequent calls.)如果您使用 LinkedHashMap 或 LinkedHashSet,迭代器应该按原始插入顺序返回对。其他 HashMap,是的,你无法控制。保留原始插入顺序在 UI 上下文中非常有用,例如,它允许您在 Web 应用程序中的任何列上重新使用表,而无需更改类型。
If you use a LinkedHashMap or LinkedHashSet the iterators are supposed to return the pairs in the original order of insertion. Other HashMaps, yeah, you have no control. Retaining the original order of insertion is quite useful in UI contexts, it allows you to resort tables on any column in a Web application without changing types, for instance.