Adds symmetric difference and cartesian product to the Counter class. I had a use case for the former and Raymond H. asked about the latter so I coded the latter from its Wikipedia description.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | import collections
class Counter(collections.Counter):
def __xor__(self, other):
''' Subtract count, but keep only abs results with non-zero counts.
>>> Counter('abbbc') ^ Counter('bccd')
Counter({'b': 2, 'a': 1, 'c': 1, 'd': 1})
>>> a, b = Counter('abbbc'), Counter('bccd')
>>> (a-b) + (b - a) == a ^ b
True
'''
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
for elem in set(self) | set(other):
newcount = self[elem] - other[elem]
if newcount != 0:
result[elem] = newcount if newcount > 0 else -newcount
return result
def __mul__(self, other):
'''Multiply counts by an integer; or cartesioan product
of two counters.
>>> Counter('abbb') * 3
Counter({'b': 9, 'a': 3})
>>> Counter('12') * Counter('21')
Counter({('2', '1'): 1, ('1', '2'): 1, ('1', '1'): 1, ('2', '2'): 1})
>>> Counter('122') * Counter('211')
Counter({('2', '1'): 4, ('1', '1'): 2, ('2', '2'): 2, ('1', '2'): 1})
'''
if isinstance(other, int):
return Counter(**dict((k, v*other)
for k,v in self.items()))
elif isinstance(other, Counter):
return Counter( (x, y)
for x in self.elements()
for y in other.elements() )
else:
return NotImplemented
def __rmul__(self, other):
'''Multiply counts by an integer; or cartesioan product
of two counters.
>>> 3 * Counter('abbb')
Counter({'b': 9, 'a': 3, 'c': 3})
'''
return self.__mul__(other)
|
The code in __mul__ was written without much thought for efficiency.
Aargh!! I forgot about copyright for the original python methods (all but __xor__ and __mul__ and __rmul__)!! Do i delete this??
I have now elided the Python code for the body of the class that needs inserting from the original Python source file collections.py
Or even better:
Thanks Rogier for your suggestion. I have updated the code.