Hacer que Counter considere dos objetos de la misma clase iguales
Frecuentes
Visto 56 veces
0
I'm using collections.Counter. It's great so far, except that I'd like it to count objects of the same class as the same. How can I do this? I tried overriding the hachís() method on the class so that all instances would hash the same. Right now, if I do Counter([Type1(), Type1(), Type2(), Type2()])
volverá {<Type1 object at...>:1,<Type1 object at...>:1,<Type2 object at...>:1,<Type2 object at...>:1}
I would prefer it to return something like {"Type1":2, "Type2":2}
instead. Is this possible? I was poking around the docs and couldn't figure out how to make it work.
I should add that the classes I'm using are essentially wrappers for constant values. It's just more convenient to wrap them in a class. Under no circumstances will one Type1 object ever differ from another Type1 object.
3 Respuestas
3
¿Qué tal esto?
Counter(type(x) for x in [Type1(), Type1(), Type2(), Type2()])
Así es como lo usaría:
>>> 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
Respondido el 09 de Septiembre de 13 a las 23:09
1
After having read your question again, I'm adding a different approach which might be more suitable to your needs.
A Counter is a dictionary, and dictionaries in Python use the __hash__
método y el __eq__
method to compare objects. So you need to define these two methods if you want objects which always compare equal and can be used as dictionary keys.
# (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
If you do the same for Type2
, you can count instances in a Counter
Me gusta esto:
>>> mycounter = Counter([Type1(), Type1(), Type2(), Type2()])
>>> mycounter
Counter({<__main__.Type1 object at ...>: 2, <__main__.Type2 object at ...>: 2})
>>> mycounter[Type1()]
2
Respondido el 10 de Septiembre de 13 a las 00:09
Ah, eq, that's what I was missing. Thank you. I actually think the approach you suggested works better for my particular situation, though this is what I was asking for! - afkbowflexina
1
If you want to group them by class name, you can use the __name__
atributo:
Counter(i.__name__ for i in (Type1(), Type2(), Type1()))
o:
from operator import attrgetter
Counter(map(attrgetter('__name__'), (Type1(), Type2(), Type1())))
Respondido el 10 de Septiembre de 13 a las 00:09
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas python data-structures collections or haz tu propia pregunta.
This is the best way. Classes can be used as dictionary keys! - un poco