summaryrefslogtreecommitdiffstats
path: root/Lib/collections
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2011-10-19 20:40:37 (GMT)
committerRaymond Hettinger <python@rcn.com>2011-10-19 20:40:37 (GMT)
commitbecd56822ac62ba2ddb4956e84f6854366945617 (patch)
treef1a399031f43a18d7784fe8f0c47d434320edb92 /Lib/collections
parent3bb8be6d78130dfcf49c4860f0009300508ff92b (diff)
downloadcpython-becd56822ac62ba2ddb4956e84f6854366945617.zip
cpython-becd56822ac62ba2ddb4956e84f6854366945617.tar.gz
cpython-becd56822ac62ba2ddb4956e84f6854366945617.tar.bz2
Issue #13121: Support in-place math operators for collections.Counter().
Diffstat (limited to 'Lib/collections')
-rw-r--r--Lib/collections/__init__.py63
1 files changed, 63 insertions, 0 deletions
diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py
index 3e864b6..68b63a8 100644
--- a/Lib/collections/__init__.py
+++ b/Lib/collections/__init__.py
@@ -683,6 +683,69 @@ class Counter(dict):
'''
return Counter() - self
+ def _keep_positive(self):
+ '''Internal method to strip elements with a negative or zero count'''
+ nonpositive = [elem for elem, count in self.items() if not count > 0]
+ for elem in nonpositive:
+ del self[elem]
+ return self
+
+ def __iadd__(self, other):
+ '''Inplace add from another counter, keeping only positive counts.
+
+ >>> c = Counter('abbb')
+ >>> c += Counter('bcc')
+ >>> c
+ Counter({'b': 4, 'c': 2, 'a': 1})
+
+ '''
+ for elem, count in other.items():
+ self[elem] += count
+ return self._keep_positive()
+
+ def __isub__(self, other):
+ '''Inplace subtract counter, but keep only results with positive counts.
+
+ >>> c = Counter('abbbc')
+ >>> c -= Counter('bccd')
+ >>> c
+ Counter({'b': 2, 'a': 1})
+
+ '''
+ for elem, count in other.items():
+ self[elem] -= count
+ return self._keep_positive()
+
+ def __ior__(self, other):
+ '''Inplace union is the maximum of value from either counter.
+
+ >>> c = Counter('abbb')
+ >>> c |= Counter('bcc')
+ >>> c
+ Counter({'b': 3, 'c': 2, 'a': 1})
+
+ '''
+ for elem, other_count in other.items():
+ count = self[elem]
+ if other_count > count:
+ self[elem] = other_count
+ return self._keep_positive()
+
+ def __iand__(self, other):
+ '''Inplace intersection is the minimum of corresponding counts.
+
+ >>> c = Counter('abbb')
+ >>> c &= Counter('bcc')
+ >>> c
+ Counter({'b': 1})
+
+ '''
+ for elem, count in self.items():
+ other_count = other[elem]
+ if other_count < count:
+ self[elem] = other_count
+ return self._keep_positive()
+
########################################################################
### ChainMap (helper for configparser and string.Template)