使Counter计算同一类的两个对象相同

时间:2013-09-09 22:44:46

标签: python data-structures collections

我正在使用collections.Counter。到目前为止它很棒,除了我想要它计算相同类的对象。我怎样才能做到这一点?我尝试重写类上的哈希()方法,以便所有实例都将哈希相同。现在,如果我Counter([Type1(), Type1(), Type2(), Type2()]),它将返回{<Type1 object at...>:1,<Type1 object at...>:1,<Type2 object at...>:1,<Type2 object at...>:1}我希望它返回{"Type1":2, "Type2":2}之类的内容。这可能吗?我在浏览文档时无法弄清楚如何使它工作。

我应该补充一点,我使用的类实际上是常量值的包装器。将它们包装在一个类中更方便。在任何情况下,一个Type1对象都不会与另一个Type1对象不同。

3 个答案:

答案 0 :(得分:3)

这个怎么样?

Counter(type(x) for x in [Type1(), Type1(), Type2(), Type2()])

这就是你如何使用它:

>>> type_counter = Counter(type(x) for x in [Type1(), Type1(), Type2(), Type2()])
>>> type_counter
Counter({<class '__main__.Type2'>: 2, <class '__main__.Type1'>: 2})
>>> type_counter[Type1]
2
>>> type_counter[type(Type2())]
2

答案 1 :(得分:1)

如果要按类名对它们进行分组,可以使用__name__属性:

Counter(i.__name__ for i in (Type1(), Type2(), Type1()))

或者:

from operator import attrgetter

Counter(map(attrgetter('__name__'), (Type1(), Type2(), Type1())))

答案 2 :(得分:1)

在再次阅读您的问题之后,我正在添加一种可能更适合您需求的不同方法。

Counter是一个字典,Python中的字典使用__hash__方法和__eq__方法来比较对象。因此,如果您希望对象始终比较相等并且可以用作字典键,则需要定义这两个方法。

# (Python 3)
class Type1:
    def __eq__(self, other):
        if isinstance(other, Type1):
            return True
        return super().__eq__(other)

    def __hash__(self):
        return 1329916036    # anything constant

如果对Type2执行相同操作,则可以按Counter计算实例,如下所示:

>>> mycounter = Counter([Type1(), Type1(), Type2(), Type2()])
>>> mycounter
Counter({<__main__.Type1 object at ...>: 2, <__main__.Type2 object at ...>: 2})
>>> mycounter[Type1()]
2