Welcome, guest | Sign In | My Account | Store | Cart

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.

Python, 52 lines
 ``` 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.

Paddy McCarthy (author) 13 years, 8 months ago

Aargh!! I forgot about copyright for the original python methods (all but __xor__ and __mul__ and __rmul__)!! Do i delete this??

Paddy McCarthy (author) 13 years, 8 months ago

I have now elided the Python code for the body of the class that needs inserting from the original Python source file collections.py

Rogier Steehouder 13 years, 8 months ago

Or even better:

``````import collections

class Counter(collections.Counter):
# only your changes go here
``````
Paddy McCarthy (author) 13 years, 8 months ago

Thanks Rogier for your suggestion. I have updated the code.

 Created by Paddy McCarthy on Tue, 17 Aug 2010 (MIT)