Commit 2876a8c2 authored by Raymond Hettinger's avatar Raymond Hettinger

Rework multiset methods to use less memory and to make fewer calls to __hash__.

parent 340d2690
...@@ -495,10 +495,13 @@ class Counter(dict): ...@@ -495,10 +495,13 @@ class Counter(dict):
if not isinstance(other, Counter): if not isinstance(other, Counter):
return NotImplemented return NotImplemented
result = Counter() result = Counter()
for elem in set(self) | set(other): for elem, count in self.items():
newcount = self[elem] + other[elem] newcount = count + other[elem]
if newcount > 0: if newcount > 0:
result[elem] = newcount result[elem] = newcount
for elem, count in other.items():
if elem not in self and count > 0:
result[elem] = count
return result return result
def __sub__(self, other): def __sub__(self, other):
...@@ -511,10 +514,13 @@ class Counter(dict): ...@@ -511,10 +514,13 @@ class Counter(dict):
if not isinstance(other, Counter): if not isinstance(other, Counter):
return NotImplemented return NotImplemented
result = Counter() result = Counter()
for elem in set(self) | set(other): for elem, count in self.items():
newcount = self[elem] - other[elem] newcount = count - other[elem]
if newcount > 0: if newcount > 0:
result[elem] = newcount result[elem] = newcount
for elem, count in other.items():
if elem not in self and count < 0:
result[elem] = 0 - count
return result return result
def __or__(self, other): def __or__(self, other):
...@@ -527,11 +533,14 @@ class Counter(dict): ...@@ -527,11 +533,14 @@ class Counter(dict):
if not isinstance(other, Counter): if not isinstance(other, Counter):
return NotImplemented return NotImplemented
result = Counter() result = Counter()
for elem in set(self) | set(other): for elem, count in self.items():
p, q = self[elem], other[elem] other_count = other[elem]
newcount = q if p < q else p newcount = other_count if count < other_count else count
if newcount > 0: if newcount > 0:
result[elem] = newcount result[elem] = newcount
for elem, count in other.items():
if elem not in self and count > 0:
result[elem] = count
return result return result
def __and__(self, other): def __and__(self, other):
...@@ -544,11 +553,9 @@ class Counter(dict): ...@@ -544,11 +553,9 @@ class Counter(dict):
if not isinstance(other, Counter): if not isinstance(other, Counter):
return NotImplemented return NotImplemented
result = Counter() result = Counter()
if len(self) < len(other): for elem, count in self.items():
self, other = other, self other_count = other[elem]
for elem in filter(self.__contains__, other): newcount = count if count < other_count else other_count
p, q = self[elem], other[elem]
newcount = p if p < q else q
if newcount > 0: if newcount > 0:
result[elem] = newcount result[elem] = newcount
return result return result
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment