['A', 'A', 'B', 'B', 'C', 'C']
# Knuth's example for prime factors of 1836: 2**2 * 3**3 * 17**1
>>> prime_factors = Counter({2: 2, 3: 3, 17: 1})
>>> for factor in prime_factors.elements(): # loop over factors
... product *= factor # and multiply them
Note, if an element's count has been set to zero or is a negative
number, elements() will ignore it.
# Emulate Bag.do from Smalltalk and Multiset.begin from C++.
return _chain.from_iterable(_starmap(_repeat, self.iteritems()))
# Override dict methods where necessary
def fromkeys(cls, iterable, v=None):
# There is no equivalent method for counters because setting v=1
# means that no element can have a count greater than one.
raise NotImplementedError(
'Counter.fromkeys() is undefined. Use Counter(iterable) instead.')
def update(*args, **kwds):
'''Like dict.update() but add counts instead of replacing them.
Source can be an iterable, a dictionary, or another Counter instance.
>>> c.update('witch') # add elements from another iterable
>>> c.update(d) # add elements from another counter
>>> c['h'] # four 'h' in which, witch, and watch
# The regular dict.update() operation makes no sense here because the
# replace behavior results in the some of original untouched counts
# being mixed-in with all of the other counts for a mismash that
# doesn't have a straight-forward interpretation in most counting
# contexts. Instead, we implement straight-addition. Both the inputs
# and outputs are allowed to contain zero and negative counts.
raise TypeError("descriptor 'update' of 'Counter' object "
raise TypeError('expected at most 1 arguments, got %d' % len(args))
iterable = args[0] if args else None
if isinstance(iterable, Mapping):
for elem, count in iterable.iteritems():
self[elem] = self_get(elem, 0) + count
super(Counter, self).update(iterable) # fast path when counter is empty
self[elem] = self_get(elem, 0) + 1
def subtract(*args, **kwds):
'''Like dict.update() but subtracts counts instead of replacing them.
Counts can be reduced below zero. Both the inputs and outputs are
allowed to contain zero and negative counts.
Source can be an iterable, a dictionary, or another Counter instance.
>>> c.subtract('witch') # subtract elements from another iterable
>>> c.subtract(Counter('watch')) # subtract elements from another counter
>>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch
>>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch
raise TypeError("descriptor 'subtract' of 'Counter' object "
raise TypeError('expected at most 1 arguments, got %d' % len(args))
iterable = args[0] if args else None
if isinstance(iterable, Mapping):
for elem, count in iterable.items():
self[elem] = self_get(elem, 0) - count
self[elem] = self_get(elem, 0) - 1
return self.__class__(self)
return self.__class__, (dict(self),)
def __delitem__(self, elem):
'Like dict.__delitem__() but does not raise KeyError for missing values.'
super(Counter, self).__delitem__(elem)
return '%s()' % self.__class__.__name__
items = ', '.join(map('%r: %r'.__mod__, self.most_common()))
return '%s({%s})' % (self.__class__.__name__, items)
# Multiset-style mathematical operations discussed in:
# Knuth TAOCP Volume II section 4.6.3 exercise 19
# and at http://en.wikipedia.org/wiki/Multiset
# Outputs guaranteed to only include positive counts.
# To strip negative and zero counts, add-in an empty counter:
def __add__(self, other):
'''Add counts from two counters.
>>> Counter('abbb') + Counter('bcc')
Counter({'b': 4, 'c': 2, 'a': 1})
if not isinstance(other, Counter):
for elem, count in self.items():
newcount = count + other[elem]
for elem, count in other.items():
if elem not in self and count > 0:
def __sub__(self, other):
''' Subtract count, but keep only results with positive counts.
>>> Counter('abbbc') - Counter('bccd')
Counter({'b': 2, 'a': 1})
if not isinstance(other, Counter):
for elem, count in self.items():
newcount = count - other[elem]
for elem, count in other.items():
if elem not in self and count < 0:
'''Union is the maximum of value in either of the input counters.
>>> Counter('abbb') | Counter('bcc')
Counter({'b': 3, 'c': 2, 'a': 1})
if not isinstance(other, Counter):
for elem, count in self.items():
other_count = other[elem]
newcount = other_count if count < other_count else count
for elem, count in other.items():
if elem not in self and count > 0:
def __and__(self, other):
''' Intersection is the minimum of corresponding counts.
>>> Counter('abbb') & Counter('bcc')
if not isinstance(other, Counter):
for elem, count in self.items():
other_count = other[elem]
newcount = count if count < other_count else other_count
if __name__ == '__main__':
# verify that instances can be pickled
from cPickle import loads, dumps
Point = namedtuple('Point', 'x, y', True)
assert p == loads(dumps(p))
# test and demonstrate ability to override methods
class Point(namedtuple('Point', 'x y')):
return (self.x ** 2 + self.y ** 2) ** 0.5
return 'Point: x=%6.3f y=%6.3f hypot=%6.3f' % (self.x, self.y, self.hypot)
for p in Point(3, 4), Point(14, 5/7.):
class Point(namedtuple('Point', 'x y')):
'Point class with optimized _make() and _replace() without error-checking'
_make = classmethod(tuple.__new__)
def _replace(self, _map=map, **kwds):
return self._make(_map(kwds.get, ('x', 'y'), self))
print Point(11, 22)._replace(x=100)
Point3D = namedtuple('Point3D', Point._fields + ('z',))
TestResults = namedtuple('TestResults', 'failed attempted')
print TestResults(*doctest.testmod())