Python comes with some builtin container data types such as lists
, tuples
, sets
, dicts
, etc. The collections
module in the standard library extends the functionality of these types by providing specialized container data structures. The data structures are as summarized below:
structure | description |
---|---|
Counter | A container that stores elements as dictionary keys, and each element's count as the value. |
deque | An implementation of a double-ended queue in which elements can be inserted and retrieved from either ends. |
namedtuple | A structure similar to tuples but in which elements can be accessed with a name not just their numeric indices. |
OrderedDict | Similar to standard dictionaries but elements are ordered by their order of insertion. |
defaultdict | A type of dictionary that allows the default value for non-existent keys to be set in advance at instantiation. |
ChainMap | A structure that links multiple mappings/dictionaries into a single unit. |
UserDict | Provides an interface for subclassing standard dict type. |
UserList | Provides an interface for subclassing standard list type. |
UserString | Provides an interface for subclassing standard str type.. |
These containers provides alternative or extension for standard data types, they have specialized features and functionality making them more suitable in some situations.
Counter data structure
Counter
objects of the collections.Counter
datatype tracks the number of occurrences of each item within a collection or sequence.
Counter(iterable = None, **kwargs)
Counter objects keeps a mapping of elements to the number of occurrences of a particular element in the given iterable
object.
We can use the update()
method of Counter objects to change the iterable after instantiation.
update(iterable=None, **kwargs)
Accessing the counts
Once the Counter object have been created, we can access the counts for a given element similarly to how we would access an element from a dictionary. In fact, the Counter class is actually a subclass of the builtin dict
class.
Thus to access the count of an element 'x' in a Counter
object with a name 'counter', we would use the following syntax.
counter['x']
The x most common elements
The Counter class defines the most_common method which gets x most common elements.
most_common(n = None)
If n
is not given, the method returns the counts of all elements
Counter arithmetic
Counter objects supports arithmetic and set operations. This makes it possible to easily do calculations on the data in the Counter object. It is possible to add two counters together, subtract one counter from another, find the union of multiple counters, and perform various other operations.
defaultdict data structure
The standard dict
type allow setting default values in cases when the value being retrieved does not exist in the dictionary. This is primarily achieved through either the get()
or the setdefault()
methods.
The defaultdict
, works similarly to the standard dicts
but it allows us to set the default value for the all keys in advance during instantiation.
default_dict(default_factory = None, *args)
The default_factory
argument is literally a function that gets called without any argument to produce the default value that will be returned if the requested item does not exist.
Deque data structure
A queue data structure is a type of a container in which elements are stored and accessed in a "first in, first out" (FIFO) manner. In double-ended queue(deque) elements can be added or removed from both ends, allowing for "first in, first out" (FIFO) and "last in, first out" (LIFO) access. This makes it a useful data structure for applications such as stacks, queues, and double-ended priority queues.
The deque
class in the collections modules provides the functionality for manipulating double-ended queues. Deque
objects support efficient insertion and removal of the entities from both ends of the queue.
Instantiating deque objects
We can simply instantiate the deque
objects without any argument to create an empty deque
. We can also pass an iterable object during instantiation to create a deque
with the elements present in the iterable.
Adding elements to the deque
We can add elements to both ends of the deque
using various methods.
adding single element
The append()
method is used to add an element at the back of the deque
.
To add an element at the front, we use the appendleft()
method.
Add multiple elements at once
The deque
class also contain methods for extending deque
objects from both ends. The extend()
methods appends iteratively all the elements of an iterable given as an argument, at the end of the deque
.
Similarly, the extendleft()
method extends the deque
object from the front.
Retrieving items from the deque
As with insertions, elements in a deque
can be retrieved from either ends. The pop()
method removes the item at the back of the deque and returns it.
The popleft()
method removes the leftmost item and returns.
deques
are thread safe, this makes it even posssible to remove items from both ends simultaneously from different threads.
rotating deque elements
Rotating is the process of moving items from one end of a deque to the other. This is useful for situations where elements need to be cycled through, such as when implementing a priority queue.
Rotating the deque to the right moves elements from the back to the front end of the deque, this is achieved using the rotate()
method with a positive value as the argument.
To rotate the deque to the left, we use the rotate()
method with a negative value.
namedtuple data structure
The namedtuple
objects are tuple-like data structures but with named fields similar to dictionaries. This makes it possible to access the items by name instead of just by indices.
When instantiating namedtuple
types we provide a type name and the values for each field.
namedtple(name, fields, rename = False, defaults = None, module = None)
name | The name of the tuple type |
fields | An iterable such as a list containg the names of the relevant fields. |
Note that just like the standard tuples, namedtuples
are Immutable and we cannot change the elements after creation.
OrderedDict data structure
In standard dict type, the order of elements is not preserved. An OrderedDict objects simply works similarly to the regular dicts
, except that OrderedDict
objects remember the order in which elements are inserted. This can be useful for tracking the order in which key-value pairs are added, as well as for outputting dictionary contents in a specific order.
Note that the order of elements will also be taken into consinderation when performing comparison operations e.g equality on OrderDicts.