What are we trying to achieve?
If you recall from last post, here's the Method Resolution Order of Counter class:
There's no way we can swap the priority order. One option is to be cheeky π and make use of the __repr__
method of builtins.dict
Option1: Casting a Counter
Object to dict
By casting the Counter
to dict
, print
will use__repr__
method of dict
which will make sure, order is maintained!
But this doesn't draw the idea home, I mean what if a novice looks at this code? He has no idea why we are casting the Counter
to dict
.
So a better approach would be to create our own custom OrderedCounter
class for clarity.
Option 2: Creating a custom OrderedCounter
class
We can create a class that inherits from Counter
and implement it's own version of __repr__
method,
The idea is still the same: cast the Counter
to dict
but this time by providing abstraction and thereby improving the readability of code.
class OrderedCounter(Counter):
'Counter that remembers the order elements are first encountered'
def __repr__(self):
# casting 'self' to dict will do the job
return '%s(%r)' % (self.__class__.__name__, dict(self))
def __reduce__(self):
return self.__class__, (dict(self),)
Here, the instantiation(creation) of OrderedCounter
Object will be done by the __init__
method of Counter
class. This means a object of type OrderedCounter
contains the count of values in iterable passed a.k.a behaves like Counter
.
The __reduce__
method implementaton is necessary for 'PICKLING' purpose which we will discuss in some other post.
OrderedCounter
in action!
# creating Ordered Counters
ordered_c0 = OrderedCounter('kkkaaaajjjjkkaaakklll')
ordered_c1 = OrderedCounter(["oranges", "apples", "apples", "bananas",
"kiwis", "kiwis", "apples"])
print(ordered_c0, ordered_c1, sep='\n')
"""OUTPUT => Order Maintained
{'k': 7, 'a': 7, 'j': 4, 'l': 3}
{'oranges': 1, 'apples': 3, 'bananas': 1, 'kiwis': 2}
"""
There are some other ways too, but knowing these two ways are more than enough!
References:
https://stackoverflow.com/questions/35446015/creating-an-ordered-counter
Top comments (0)