10

如何使用以下定义测试一个 pythonCounter是否包含在另一个中:

当且仅当对于 中的每个键,值小于或等于值时,计数器才a包含在计数器中。包含在但不包含在 中。bkaa[k]b[k]Counter({'a': 1, 'b': 1})Counter({'a': 2, 'b': 2})Counter({'a': 2, 'c': 2})

我认为这是一个糟糕的设计选择,但在 python 2.x中,比较运算符 ( <, <=, >=, >) 不使用前面的定义,因此第三个 Counter 被认为大于第一个。相反,在 python 3.x中,Counter是不可排序的类型

4

4 回答 4

14

虽然Counter实例无法与<and>运算符进行比较,但您可以发现它们与-运算符的区别。差异永远不会返回负数,因此如果A - B为空,则您知道B包含 中的所有项目A

def contains(larger, smaller):
    return not smaller - larger
于 2015-04-11T09:07:48.203 回答
13

我想出的最好的方法是转换我在代码中给出的定义:

def contains(container, contained):
    return all(container[x] >= contained[x] for x in contained)

但是如果觉得奇怪的是 python 没有开箱即用的解决方案,我必须为每个运算符编写一个函数(或者制作一个通用的并传递比较函数)。

于 2015-04-11T08:12:23.803 回答
1

对于较小的所有键,请Counter确保没有值大于较大的对应值Counter

def containment(big, small):
    return not any(v > big[k] for (k, v) in small.iteritems())

>>> containment(Counter({'a': 2, 'b': 2}), Counter({'a': 1, 'b': 1}))
True
>>> containment(Counter({'a': 2, 'c': 2, 'b': 3}), Counter({'a': 2, 'b': 2}))
True
>>> print containment(Counter({'a': 2, 'b': 2}), Counter({'a': 2, 'b': 2, 'c':1}))
False
>>> print containment(Counter({'a': 2, 'c': 2}), Counter({'a': 1, 'b': 1})
False
于 2015-04-12T07:46:17.053 回答
0

另一种相当简洁的表达方式:

“计数器 A 是计数器 B 的子集”等价于(A & B) == A

这是因为两个 Counter 的交集 ( &) 具有两者共有的元素计数。这就像(counting multiplicity) 的A每个元素A也在B; 否则它会更小。

在性能方面,这似乎与not A - BBlckknght 提出的方法大致相同。按照 enrico.bacis 的答案检查每个键要快得多。

作为一种变体,您还可以检查并集是否等于较大的 Counter(因此没有添加任何内容)(A | B) == B:。对于我测试的一些较大的多重集(1,000,000 个元素)来说,这明显变慢了。

于 2021-05-14T03:04:57.020 回答