summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2011-04-17 20:08:41 -0700
committerRaymond Hettinger <python@rcn.com>2011-04-17 20:08:41 -0700
commitefeb8bdaa2102208e765610fc2f84482b321ef5b (patch)
treeb72dbeac10c40ba90cf5b2abd746c615de0ed549
parentc116da04a96f173230fa8635adb69a1d83d21c0d (diff)
downloadcpython-git-efeb8bdaa2102208e765610fc2f84482b321ef5b.tar.gz
Rework multiset methods to use less memory and to make fewer calls to __hash__.
-rw-r--r--Lib/collections.py31
1 files changed, 19 insertions, 12 deletions
diff --git a/Lib/collections.py b/Lib/collections.py
index cb720ac9ab..3c54690eb5 100644
--- a/Lib/collections.py
+++ b/Lib/collections.py
@@ -552,10 +552,13 @@ class Counter(dict):
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
- for elem in set(self) | set(other):
- newcount = self[elem] + other[elem]
+ for elem, count in self.items():
+ newcount = count + other[elem]
if newcount > 0:
result[elem] = newcount
+ for elem, count in other.items():
+ if elem not in self and count > 0:
+ result[elem] = count
return result
def __sub__(self, other):
@@ -568,10 +571,13 @@ class Counter(dict):
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
- for elem in set(self) | set(other):
- newcount = self[elem] - other[elem]
+ for elem, count in self.items():
+ newcount = count - other[elem]
if newcount > 0:
result[elem] = newcount
+ for elem, count in other.items():
+ if elem not in self and count < 0:
+ result[elem] = 0 - count
return result
def __or__(self, other):
@@ -584,11 +590,14 @@ class Counter(dict):
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
- for elem in set(self) | set(other):
- p, q = self[elem], other[elem]
- newcount = q if p < q else p
+ for elem, count in self.items():
+ other_count = other[elem]
+ newcount = other_count if count < other_count else count
if newcount > 0:
result[elem] = newcount
+ for elem, count in other.items():
+ if elem not in self and count > 0:
+ result[elem] = count
return result
def __and__(self, other):
@@ -601,11 +610,9 @@ class Counter(dict):
if not isinstance(other, Counter):
return NotImplemented
result = Counter()
- if len(self) < len(other):
- self, other = other, self
- for elem in _ifilter(self.__contains__, other):
- p, q = self[elem], other[elem]
- newcount = p if p < q else q
+ for elem, count in self.items():
+ other_count = other[elem]
+ newcount = count if count < other_count else other_count
if newcount > 0:
result[elem] = newcount
return result