While another thread is talking about an ordered dict, I thought I'd
try a simple implementation of a bag/multiset in Python. Comments/
suggestions welcome, etc.
class bag(object):
def __add__(self, other):
result = self.copy()
for item, count in other.iteritems ():
result._items[item] = result._items.g et(item, 0) + count
return result
def __and__(self, other):
result = bag()
for item, count in other.iteritems ():
new_count = min(self._items .get(item, 0), count)
if new_count 0:
result._items[item] = new_count
return result
def __contains__(se lf, item):
return item in self._items
def __eq__(self, other):
return self._items == other._items
def __getitem__(sel f, item):
return self._items[item]
def __iadd__(self, other):
self._items = self.__add__(ot her)._items
return self
def __iand__(self, other):
self._items = self.__and__(ot her)._items
return self
def __init__(self, iterable=None):
self._items = {}
if iterable is not None:
for item in iterable:
self._items[item] = self._items.get (item, 0) + 1
def __ior__(self, other):
self._items = self.__or__(oth er)._items
return self
def __isub__(self, other):
self._items = self.__sub__(ot her)._items
return self
def __iter__(self):
for item, count in self.iteritems( ):
for counter in xrange(count):
yield item
def __ixor__(self, other):
self._items = self.__xor__(ot her)._items
return self
def __len__(self):
return sum(self._items .itervalues())
def __ne__(self, other):
return self._items != other._items
def __or__(self, other):
result = self.copy()
for item, count in other.iteritems ():
result._items[item] = max(result._ite ms.get(item, 0),
count)
return result
def __repr__(self):
result = []
for item, count in self.iteritems( ):
result += [repr(item)] * count
return 'bag([%s])' % ', '.join(result)
def __setitem__(sel f, item, count):
if not isinstance(coun t, int) or count < 0:
raise ValueError
if count 0:
self._items[item] = count
elif item in self._items:
del self._items[item]
def __sub__(self, other):
result = bag()
for item, count in self.iteritems( ):
new_count = count - other._items.ge t(item, 0)
if new_count 0:
result._items[item] = new_count
return result
def __xor__(self, other):
result = self.copy()
for item, count in other.iteritems ():
new_count = abs(result._ite ms.get(item, 0) - count)
if new_count 0:
result._items[item] = new_count
elif item in result._item:
del result._items[item]
return result
def add(self, item):
self._items[item] = self._items.get (item, 0) + 1
def discard(self, item):
new_count = self._items.get (item, 0) - 1
if new_count 0:
self._items[item] = new_count
elif new_count == 0:
del self._items[item]
def clear(self):
self._items = {}
def copy(self):
result = bag()
result._items = self._items.cop y()
return result
def difference(self , other):
return self.__sub__(ot her)
def difference_upda te(self, other):
self._items = self.__sub__(ot her)._items
def get(self, item, default=0):
return self._items.get (item, default)
def intersection(se lf, other):
return self.__and__(ot her)
def intersection_up date(self, other):
self.__iand__(o ther)
def items(self):
return self._items.ite ms()
def iteritems(self) :
return self._items.ite ritems()
def iterkeys(self):
return self._items.ite rkeys()
def itervalues(self ):
return self._items.ite rvalues()
def keys(self):
return self._items.key s()
def pop(self):
item = self._items.key s()[0]
self._items[item] -= 1
if self._items[item] == 0:
del self._items[item]
return item
def remove(self, item):
new_count = self._items[item] - 1
if new_count 0:
self._items[item] = new_count
else:
del self._items[item]
def symmetric_diffe rence(self, other):
return self.__xor__(ot her)
def symmetric_diffe rence_update(se lf, other):
self.__ixor__(o ther)
def union(self, other):
return self.__or__(oth er)
def update(self, other):
self.__ior__(ot her)
def values(self):
return self._items.val ues()
try a simple implementation of a bag/multiset in Python. Comments/
suggestions welcome, etc.
class bag(object):
def __add__(self, other):
result = self.copy()
for item, count in other.iteritems ():
result._items[item] = result._items.g et(item, 0) + count
return result
def __and__(self, other):
result = bag()
for item, count in other.iteritems ():
new_count = min(self._items .get(item, 0), count)
if new_count 0:
result._items[item] = new_count
return result
def __contains__(se lf, item):
return item in self._items
def __eq__(self, other):
return self._items == other._items
def __getitem__(sel f, item):
return self._items[item]
def __iadd__(self, other):
self._items = self.__add__(ot her)._items
return self
def __iand__(self, other):
self._items = self.__and__(ot her)._items
return self
def __init__(self, iterable=None):
self._items = {}
if iterable is not None:
for item in iterable:
self._items[item] = self._items.get (item, 0) + 1
def __ior__(self, other):
self._items = self.__or__(oth er)._items
return self
def __isub__(self, other):
self._items = self.__sub__(ot her)._items
return self
def __iter__(self):
for item, count in self.iteritems( ):
for counter in xrange(count):
yield item
def __ixor__(self, other):
self._items = self.__xor__(ot her)._items
return self
def __len__(self):
return sum(self._items .itervalues())
def __ne__(self, other):
return self._items != other._items
def __or__(self, other):
result = self.copy()
for item, count in other.iteritems ():
result._items[item] = max(result._ite ms.get(item, 0),
count)
return result
def __repr__(self):
result = []
for item, count in self.iteritems( ):
result += [repr(item)] * count
return 'bag([%s])' % ', '.join(result)
def __setitem__(sel f, item, count):
if not isinstance(coun t, int) or count < 0:
raise ValueError
if count 0:
self._items[item] = count
elif item in self._items:
del self._items[item]
def __sub__(self, other):
result = bag()
for item, count in self.iteritems( ):
new_count = count - other._items.ge t(item, 0)
if new_count 0:
result._items[item] = new_count
return result
def __xor__(self, other):
result = self.copy()
for item, count in other.iteritems ():
new_count = abs(result._ite ms.get(item, 0) - count)
if new_count 0:
result._items[item] = new_count
elif item in result._item:
del result._items[item]
return result
def add(self, item):
self._items[item] = self._items.get (item, 0) + 1
def discard(self, item):
new_count = self._items.get (item, 0) - 1
if new_count 0:
self._items[item] = new_count
elif new_count == 0:
del self._items[item]
def clear(self):
self._items = {}
def copy(self):
result = bag()
result._items = self._items.cop y()
return result
def difference(self , other):
return self.__sub__(ot her)
def difference_upda te(self, other):
self._items = self.__sub__(ot her)._items
def get(self, item, default=0):
return self._items.get (item, default)
def intersection(se lf, other):
return self.__and__(ot her)
def intersection_up date(self, other):
self.__iand__(o ther)
def items(self):
return self._items.ite ms()
def iteritems(self) :
return self._items.ite ritems()
def iterkeys(self):
return self._items.ite rkeys()
def itervalues(self ):
return self._items.ite rvalues()
def keys(self):
return self._items.key s()
def pop(self):
item = self._items.key s()[0]
self._items[item] -= 1
if self._items[item] == 0:
del self._items[item]
return item
def remove(self, item):
new_count = self._items[item] - 1
if new_count 0:
self._items[item] = new_count
else:
del self._items[item]
def symmetric_diffe rence(self, other):
return self.__xor__(ot her)
def symmetric_diffe rence_update(se lf, other):
self.__ixor__(o ther)
def union(self, other):
return self.__or__(oth er)
def update(self, other):
self.__ior__(ot her)
def values(self):
return self._items.val ues()