¿Cómo obtener la salida del contador de python ordenada por orden de entradas?

He estado trabajando para obtener el recuento (frecuencia) y luego hacer la representación gráfica de él.

Estoy usando la clase Counter de collections usando python. Quiero la salida del Counter en el orden del primer objeto.

por ejemplo:

 offset=['a','b','c','a','b','b','b','c','c','c','c','c'] counts = Counter(offset) print counts 

la salida es:

 Counter({'c': 6, 'b': 4, 'a': 2}) 

Como quiero que la salida sea la siguiente, en el orden del primer objeto:

 Counter({'a': 2, 'b': 4, 'c': 6}) 

¿Es eso posible?

Gracias

OrderedCounter por (2 líneas de longitud) herencia múltiple

Siguiendo el maravilloso discurso de Supermond Super Ray Ray Hettinger, podemos usar la herencia múltiple:

 from collections import OrderedDict, Counter class OrderedCounter(Counter, OrderedDict): pass 

y úsalo:

 >>> counter = OrderedCounter("abracadabra") >>> for key, value in counter.items(): ... print key, value a 5 b 2 r 2 c 1 d 1 

Esto es todo lo que necesitas para tu tarea.

Arreglando una representación un tanto confusa.

Hagamos un poco más de pruebas y veamos qué “resultados” obtenemos:

 >>> counter = OrderedCounter("cbaaa") >>> counter OrderedCounter({'a': 3, 'c': 1, 'b': 1}) 

Oh, esto se ve mal, el orden esperado es “c”, “b”, “a”. Vamos a probarlo imprimiendo las claves y valores:

 >>> for key, value in counter.items(): ... print key, value c 1 b 1 a 3 

Esto parece correcto (y es exactamente lo que realmente cuenta para usar en su código).

Resulta que la clase que hemos creado está produciendo una representación un poco confusa.

Esto puede ser arreglado:

 class OrderedCounter(Counter, OrderedDict): def __repr__(self): return "%s(%r)" % (self.__class__.__name__, OrderedDict(self)) 

y cuando se usa:

 >>> counter = OrderedCounter("cbaaa") >>> counter OrderedCounter({'c': 1, 'b': 1, 'a': 1}) 

Versión completa del discurso de Raymond Hettinger (agregado decapado)

La versión completa proporcionada en el discurso está agregando un método más __reduce__ que permite decapar el objeto correctamente.

 from collections import OrderedDict, Counter class OrderedCounter(Counter, OrderedDict): """Counter that remembers the order elements are first seen""" def __repr__(self): return "%s(%r)" % (self.__class_.__name__, OrderedDict(self)) def __reduce__(self): return self.__class__, (OrderedDict(self),) 

De todos modos, en la mayoría de los casos, se administrará con la versión más simple de la clase OrderedCounter .

EDITAR

Lo siento, he entendido mal. prueba esto. Lo implementé utilizando el concepto de cola.

 q = [] ret = [] for i in offset: if q.count(i)==0: q.insert(i, 0) while len(q): item = q.pop() ret.append((item, d.get(item))) print(ret) 

Los diccionarios en python son simplemente tablas hash, por lo que no tienen ningún tipo de orden. Nunca se puede imprimir una lista ordenada. Pero puedes convertirlos en una lista de tuplas y ordenar eso.

 from collections import Counter import operator offset=['a','b','c','a','b','b','b','c','c','c','c','c'] counts = Counter(offset) print(sorted(counts.items(), key=operator.itemgetter(0))) #[('a', 2), ('b', 4), ('c', 6)] 

Tendrá que hacerlo “a la manera antigua” utilizando un diccionario ordenado que garantice mantener el orden en que se insertan los elementos por primera vez:

 from collections import OrderedDict offset = ['a','b','c','a','b','b','b','c','c','c','c','c'] counts = OrderedDict() for elt in offset: try: counts[elt] += 1 except KeyError: counts[elt] = 1 print(counts) 

Resultado:

 OrderedDict([('a', 2), ('b', 4), ('c', 6)]) 

Puede utilizar dicha metodología:

 from collections import Counter offset=['a','b','c','a','b','b','b','c','c','c','c','c'] counts = Counter(offset) for letter in offset: if letter in counts: print (letter + ": " + str(counts[letter])) counts.pop(letter) 

Eso funciona de la siguiente manera:

 >>> ================================ RESTART ================================ >>> a: 2 b: 4 c: 6 

Puede almacenar los pares en una lista en lugar de imprimir.