【问题标题】:Unexpected behaviour in Python OrderedSet.issuperset()Python OrderedSet.issuperset() 中的意外行为
【发布时间】:2015-06-18 18:18:55
【问题描述】:

我有两个 OrderedSet,我正在尝试检查一个是否在另一个的子集中 - 元素及其顺序都很重要。但是,orderedset 包给了我奇怪的结果。

>>> import orderedset
>>> a = orderedset.OrderedSet([433, 316, 259])
>>> b = orderedset.OrderedSet([433, 316, 69])
>>> a.issuperset(b)
True

这对我来说没有任何意义,因为b 包含一个绝对不在a 中的值 (69)。那么为什么asupersetb 呢?

但是,当我尝试这个时:

>>> c = orderedset.OrderedSet([1, 2, 3])
>>> d = orderedset.OrderedSet([1, 2, 4])
>>> c.issuperset(d)
False

这种行为对我来说似乎不一致:为什么 OrderedSet 中值的选择 - [433, 316, 259][1, 2, 3] - 会影响 issuperset() 的输出?

也许有更好的方法来做到这一点?我需要知道b 中的元素是否以相同的顺序包含在a 中。意思是,如果

a = OrderedSet([433, 316, 259])

我正在该集合中寻找以与a (433) 相同的起始值开头的部分匹配项。这就是我想要的:

OrderedSet([433, 316, 259])
OrderedSet([433, 316]])
OrderedSet([433])

而不是:

OrderedSet([433, 259])
OrderedSet([316, 259])
OrderedSet([433, 316, 69])
OrderedSet([433, 259, 316])
OrderedSet([259, 433])
...

基本上,如果这真的令人困惑 - 我有一个有序的集合,我试图在值和它们的顺序方面找到部分匹配。

【问题讨论】:

  • 我不认为issuperset 在这里可以正常工作——它通常假设是有序集合。

标签: python set set-theory


【解决方案1】:

大概你正在使用这个third party module,因为 Python 没有内置的有序集。

快速浏览source code on github 表明issuperset 函数实现为

def issuperset(self, other):
    return other <= self

看看如何为orderedset定义小于或等于运算符:

def __le__(self, other):
    if isinstance(other, _OrderedSet):
        return len(self) <= len(other) and list(self) <= list(other)

所以本质上,当比较两个有序集合时,首先将它们转换为列表,然后使用 Python 内置的&lt;= 来比较两个列表。当您使用&lt;= 比较两个列表时,它类似于词法字符串比较,即比较两个列表的匹配索引。

根据他们的实现,[433, 316, 259][433, 316, 69] 的超集(第一个列表的所有匹配索引都大于或等于第二个列表),而[433, 316, 259] 不会是[433, 316, 260] 的超集(第二个列表在其最后一个索引中的值大于第一个列表)。

他们可能想写的是

return len(self) <= len(other) and set(self) <= set(other)

这将使用为内置 Python 集定义的 &lt;=,并正确测试子集和超集。

您可能想report this issue here

【讨论】:

  • 谢谢,我想我现在明白这个问题了。我想部分原因是为有序集定义超集/子集是模棱两可的。我想我应该写一些特别适合我需要的东西,而不是依赖外部定义。我会报告这个错误,以便他们知道。如果您对我如何实现这一点(有用的构造等)有任何建议,我将不胜感激。
  • 您在测试超集或子集时是否关心顺序?根据定义,集合没有顺序,因此这种行为实际上是未定义的。
  • 我对订购和会员资格感兴趣 - 我想知道我的订购集有多少部分匹配。因此,在示例中,[433, 316, 259] 表示用户在网站上执行的一系列操作。例如,我想知道有多少用户完成了整个操作集,有多少用户只完成了序列[433, 316] 中的前两个操作,以及有多少用户在完成第一个操作[433] 后刚刚停止。也许有更好的方法来表示和处理这些信息?
  • 根据您更新的问题,您似乎并不真正需要集合的属性,您只需要订购。在这种情况下,您可以只使用一个列表。您的问题似乎归结为“列表中是否存在子列表”。如果是这种情况,请尝试查看这里:stackoverflow.com/questions/10106901/…
猜你喜欢
  • 1970-01-01
  • 2017-03-05
  • 2014-02-27
  • 1970-01-01
  • 1970-01-01
  • 2011-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多