diff options
author | Raymond Hettinger <python@rcn.com> | 2010-04-03 10:22:00 (GMT) |
---|---|---|
committer | Raymond Hettinger <python@rcn.com> | 2010-04-03 10:22:00 (GMT) |
commit | 34c35b2788f4f764022f11a624fb08d325c31e94 (patch) | |
tree | 69659df9223549ce681e931048c4bd38c2aab980 /Lib | |
parent | f70c5810565728b29a375492d5c3a37c5aa9af91 (diff) | |
download | cpython-34c35b2788f4f764022f11a624fb08d325c31e94.zip cpython-34c35b2788f4f764022f11a624fb08d325c31e94.tar.gz cpython-34c35b2788f4f764022f11a624fb08d325c31e94.tar.bz2 |
Add subtract() method to collections.Counter() objects.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/collections.py | 28 | ||||
-rw-r--r-- | Lib/test/test_collections.py | 11 |
2 files changed, 39 insertions, 0 deletions
diff --git a/Lib/collections.py b/Lib/collections.py index 0322669..9edc294 100644 --- a/Lib/collections.py +++ b/Lib/collections.py @@ -435,6 +435,34 @@ class Counter(dict): if kwds: self.update(kwds) + def subtract(self, iterable=None, **kwds): + '''Like dict.update() but subtracts counts instead of replacing them. + Counts can be reduced below zero. Both the inputs and outputs are + allowed to contain zero and negative counts. + + Source can be an iterable, a dictionary, or another Counter instance. + + >>> c = Counter('which') + >>> c.subtract('witch') # subtract elements from another iterable + >>> c.subtract(Counter('watch')) # subtract elements from another counter + >>> c['h'] # 2 in which, minus 1 in witch, minus 1 in watch + 0 + >>> c['w'] # 1 in which, minus 1 in witch, minus 1 in watch + -1 + + ''' + if iterable is not None: + if isinstance(iterable, Mapping): + self_get = self.get + for elem, count in iterable.items(): + self[elem] = self_get(elem, 0) - count + else: + self_get = self.get + for elem in iterable: + self[elem] = self_get(elem, 0) - 1 + if kwds: + self.subtract(kwds) + def copy(self): 'Like dict.copy() but returns a Counter instance instead of a dict.' return Counter(self) diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py index a7be8d5..4330583 100644 --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -669,6 +669,17 @@ class TestCounter(unittest.TestCase): set_result = setop(set(p.elements()), set(q.elements())) self.assertEqual(counter_result, dict.fromkeys(set_result, 1)) + def test_subtract(self): + c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) + c.subtract(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50) + self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50)) + c = Counter(a=-5, b=0, c=5, d=10, e=15,g=40) + c.subtract(Counter(a=1, b=2, c=-3, d=10, e=20, f=30, h=-50)) + self.assertEqual(c, Counter(a=-6, b=-2, c=8, d=0, e=-5, f=-30, g=40, h=50)) + c = Counter('aaabbcd') + c.subtract('aaaabbcce') + self.assertEqual(c, Counter(a=-1, b=0, c=-1, d=1, e=-1)) + class TestOrderedDict(unittest.TestCase): def test_init(self): |