DEV Community

Cover image for Python's Collections Module: OrderedCounter
Kathan Vakharia
Kathan Vakharia

Posted on

4 2

Python's Collections Module: OrderedCounter

What are we trying to achieve?

If you recall from last post, here's the Method Resolution Order of Counter class:
imageThere'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!

imageBut 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),)
Enter fullscreen mode Exit fullscreen mode

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}
"""
Enter fullscreen mode Exit fullscreen mode

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

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay