Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the python Counter output ordered by order of inputs?

I have been working on getting the count(frequency) and then making the graph representation of it.

I am using Counter class from collections using python. I want the output of the Counter in the order of the first come object.

for example:

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

output is:

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

As I want the output to be as follows, in the order of the first come object:

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

Is that possible?

Thanks

like image 796
hrishabh upadhyay Avatar asked Apr 23 '16 06:04

hrishabh upadhyay


People also ask

Is counter in python ordered?

Python Counter Counter is an unordered collection where elements are stored as Dict keys and their count as dict value. Counter elements count can be positive, zero or negative integers. However there is no restriction on it's keys and values.

How do I extract a value from a counter in python?

Accessing Elements in Python Counter To get the list of elements in the counter we can use the elements() method. It returns an iterator object for the values in the Counter.

What is collections counter () in python?

A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts.


1 Answers

OrderedCounter by (2 lines long) multiple inheritance

Following wonderful speech Super considered super by Raymond Hettinger we can use multiple inheritance:

from collections import OrderedDict, Counter

class OrderedCounter(Counter, OrderedDict):
    pass

and use it:

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

This is all you need for your task.

Fixing a slightly confusing representation

Let us do a bit more tests and see, what "result" we get:

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

Oh - this looks wrong, expected order is "c", "b", "a". Let us test it printing the keys and values:

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

This looks correct (and it is exactly what really counts for using in your code).

It turns out, that the class we have created is just producing a bit confusing representation.

This can be fixed:

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

and when used:

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

Full version from the Raymond Hettinger speech (added pickling)

Full version provided in the speech is adding one more method __reduce__ which allows pickling the object properly.

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),)

Anyway, in most cases you will manage with the simplest version of the OrderedCounter class.

like image 68
Jan Vlcinsky Avatar answered Oct 05 '22 23:10

Jan Vlcinsky