# EXOR or symmetric difference for the Counter class

Tue Aug 17 23:47:55 CEST 2010

```On 17 Aug, 02:29, Raymond Hettinger <pyt... at rcn.com> wrote:
>
> > 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