On Aug 17, 10:47 pm, Paddy <paddy3...@googlemail.com> wrote: > On 17 Aug, 02:29, Raymond Hettinger <pyt...@rcn.com> wrote: > > > > > [Paddy] > > > > Lets say you have two *sets* of integers representing two near-copies > > > of some system, then a measure of their difference could be calculated > > > as: > > > > len(X.symmetric_difference(Y)) / (len(X) + len(Y)) * 100 % > > > > If the two collections of integers are allowed duplicates then you > > > need a Counter/bag/multi-set type and the diff calculation I gave > > > originally. > > > Thanks for sharing your use case. > > > It's unlikely that I will add this method to the Counter API because > > the rarity of use case does not warrant the added API complexity. > > IMO, adding a method like this makes the class harder to learn, > > understand and remember. It doesn't seem like much of a win over > > using the existing alternatives: > > > * (b - c) + (c - b) > > * (b | c) - (b & c) > > * DIY using the two counters as simple dicts > > * writing a subclass providing additional binary operations > > > I would like to see someone post a subclass to the ASPN Cookbook that > > adds a number of interesting, though not common operations. Your > > symmetric_difference() method could be one. A dot_product() operation > > could be another. Elementwise arithmetic is another option (we > > already have add and subtract, but could possibly use multiply, > > divide, etc). Scaling operations are another possibility (multiple > > all elements by five, for example). > > > The Counter() class has low aspirations. It is a dictionary that > > fills-in missing values with zero and is augmented by a handful of > > basic methods for managing the counts. > > > Raymond > > I created this that could be an addition to the bottom of the Python 3 > collections.Counter class definition: > > def __xor__(self, other): > ''' symmetric difference: 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 > > - Paddy.
And heres the cartesian product/multiply: 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 (Although I don't have a use case for this one). - Paddy. -- http://mail.python.org/mailman/listinfo/python-list