测试python Counter是否包含在另一个Counter中

时间:2015-04-11 08:12:24

标签: python algorithm counter inclusion

如何使用以下定义测试另一个python Counter是否包含

  

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

我认为这是一个糟糕的设计选择,但在python 2.x 比较运算符(<<=>=,{{1} })不要使用先前的定义,因此第三个计数器被认为是大于的第一个。在python 3.x 中,>无法解决的类型

4 个答案:

答案 0 :(得分:9)

虽然Counter个实例与<>运算符不具有可比性,但您可以找到它们与-运算符的区别。差异永远不会返回负数,因此如果A - B为空,则表示B包含A中的所有项目。

def contains(larger, smaller):
    return not smaller - larger

答案 1 :(得分:6)

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

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

但是如果感觉很奇怪,python没有开箱即用的解决方案,我必须为每个运营商编写一个函数(或者创建一个通用函数并传递比较函数) )。

答案 2 :(得分:0)

对于较小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

答案 3 :(得分:0)

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

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

那是因为两个 Counters 的交集 (&) 具有两者共有的元素计数。如果 A 的每个元素(计数多重性)也在 A 中,则这将与 B 相同;否则会更小。

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

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