[Python-checkins] r68843 - in python/trunk: Doc/library/collections.rst Lib/collections.py Lib/test/test_collections.py

raymond.hettinger python-checkins at python.org
Wed Jan 21 21:31:50 CET 2009


Author: raymond.hettinger
Date: Wed Jan 21 21:31:50 2009
New Revision: 68843

Log:
Simplify explanation of multiset operations by removing restrictions on negative inputs.

Modified:
   python/trunk/Doc/library/collections.rst
   python/trunk/Lib/collections.py
   python/trunk/Lib/test/test_collections.py

Modified: python/trunk/Doc/library/collections.rst
==============================================================================
--- python/trunk/Doc/library/collections.rst	(original)
+++ python/trunk/Doc/library/collections.rst	Wed Jan 21 21:31:50 2009
@@ -265,16 +265,18 @@
     c.items()                     # convert to a list of (elem, cnt) pairs
     Counter(dict(list_of_pairs))  # convert from a list of (elem, cnt) pairs
     c.most_common()[:-n:-1]       # n least common elements
+    c += Counter()                # remove zero and negative counts
 
 Several multiset mathematical operations are provided for combining
-:class:`Counter` objects.  Multisets are like regular sets but allowed to
+:class:`Counter` objects.  Multisets are like regular sets but are allowed to
 contain repeated elements (with counts of one or more).  Addition and
 subtraction combine counters by adding or subtracting the counts of
 corresponding elements.  Intersection and union return the minimum and maximum
-of corresponding counts::
+of corresponding counts.  All four multiset operations exclude results with
+zero or negative counts::
 
-    >>> c = Counter({'a': 3, 'b': 1})
-    >>> d = Counter({'a': 1, 'b': 2})
+    >>> c = Counter(a=3, b=1)
+    >>> d = Counter(a=1, b=2)
     >>> c + d                           # add two counters together:  c[x] + d[x]
     Counter({'a': 4, 'b': 3})
     >>> c - d                           # subtract (keeping only positive counts)
@@ -284,16 +286,6 @@
     >>> c | d                           # union:  max(c[x], d[x])
     Counter({'a': 3, 'b': 2})
 
-All four multiset operations produce only positive counts (negative and zero
-results are skipped). If inputs include negative counts, addition will sum
-both counts and then exclude non-positive results.  The other three operations
-are undefined for negative inputs::
-
-    >>> e = Counter(a=8, b=-2, c=0)
-    >>> e += Counter()                  # remove zero and negative counts
-    >>> e
-    Counter({'a': 8})
-
 .. seealso::
 
     * `Bag class <http://www.gnu.org/software/smalltalk/manual-base/html_node/Bag.html>`_

Modified: python/trunk/Lib/collections.py
==============================================================================
--- python/trunk/Lib/collections.py	(original)
+++ python/trunk/Lib/collections.py	Wed Jan 21 21:31:50 2009
@@ -312,8 +312,8 @@
         if not isinstance(other, Counter):
             return NotImplemented
         result = Counter()
-        for elem, count in self.iteritems():
-            newcount = count - other[elem]
+        for elem in set(self) | set(other):
+            newcount = self[elem] - other[elem]
             if newcount > 0:
                 result[elem] = newcount
         return result

Modified: python/trunk/Lib/test/test_collections.py
==============================================================================
--- python/trunk/Lib/test/test_collections.py	(original)
+++ python/trunk/Lib/test/test_collections.py	Wed Jan 21 21:31:50 2009
@@ -457,18 +457,19 @@
         for i in range(1000):
             # test random pairs of multisets
             p = Counter(dict((elem, randrange(-2,4)) for elem in elements))
+            p.update(e=1, f=-1, g=0)
             q = Counter(dict((elem, randrange(-2,4)) for elem in elements))
-            for counterop, numberop, defneg in [
-                (Counter.__add__, lambda x, y: x+y if x+y>0 else 0, True),
-                (Counter.__sub__, lambda x, y: x-y if x-y>0 else 0, False),
-                (Counter.__or__, max, False),
-                (Counter.__and__, min, False),
+            q.update(h=1, i=-1, j=0)
+            for counterop, numberop in [
+                (Counter.__add__, lambda x, y: max(0, x+y)),
+                (Counter.__sub__, lambda x, y: max(0, x-y)),
+                (Counter.__or__, lambda x, y: max(0,x,y)),
+                (Counter.__and__, lambda x, y: max(0, min(x,y))),
             ]:
                 result = counterop(p, q)
                 for x in elements:
-                    # all except __add__ are undefined for negative inputs
-                    if defneg or (p[x] >= 0 and q[x] >= 0):
-                        self.assertEqual(numberop(p[x], q[x]), result[x])
+                    self.assertEqual(numberop(p[x], q[x]), result[x],
+                                     (counterop, x, p, q))
                 # verify that results exclude non-positive counts
                 self.assert_(x>0 for x in result.values())
 


More information about the Python-checkins mailing list