[Python-checkins] r84568 - in python/branches/py3k: Doc/library/collections.rst Lib/collections.py Lib/functools.py Lib/test/test_collections.py Misc/NEWS

raymond.hettinger python-checkins at python.org
Mon Sep 6 23:26:09 CEST 2010


Author: raymond.hettinger
Date: Mon Sep  6 23:26:09 2010
New Revision: 84568

Log:
Add method to OrderedDict for repositioning keys to the ends.

Modified:
   python/branches/py3k/Doc/library/collections.rst
   python/branches/py3k/Lib/collections.py
   python/branches/py3k/Lib/functools.py
   python/branches/py3k/Lib/test/test_collections.py
   python/branches/py3k/Misc/NEWS

Modified: python/branches/py3k/Doc/library/collections.rst
==============================================================================
--- python/branches/py3k/Doc/library/collections.rst	(original)
+++ python/branches/py3k/Doc/library/collections.rst	Mon Sep  6 23:26:09 2010
@@ -793,6 +793,23 @@
       (key, value) pair.  The pairs are returned in LIFO order if *last* is true
       or FIFO order if false.
 
+   .. method:: move_to_end(key, last=True)
+
+      Move an existing *key* to either end of an ordered dictionary.  The item
+      is moved to the right end if *last* is true (the default) or to the
+      beginning if *last* is false.  Raises :exc:`KeyError` if the *key* does
+      not exist::
+
+          >>> d = OrderedDict.fromkeys('abcde')
+          >>> d.move_to_end('b')
+          >>> ''.join(d.keys)
+          'acdeb'
+          >>> d.move_to_end('b', 0)
+          >>> ''.join(d.keys)
+          'bacde'
+
+      .. versionadded:: 3.2
+
 In addition to the usual mapping methods, ordered dictionaries also support
 reverse iteration using :func:`reversed`.
 

Modified: python/branches/py3k/Lib/collections.py
==============================================================================
--- python/branches/py3k/Lib/collections.py	(original)
+++ python/branches/py3k/Lib/collections.py	Mon Sep  6 23:26:09 2010
@@ -173,18 +173,29 @@
     def __del__(self):
         self.clear()                # eliminate cyclical references
 
-    def _renew(self, key, PREV=0, NEXT=1):
-        'Fast version of self[key]=self.pop(key).   Private method for internal use.'
+    def move_to_end(self, key, last=True, PREV=0, NEXT=1):
+        '''Move an existing element to the end (or beginning if last==False).
+
+        Raises KeyError if the element does not exist.
+        When last=True, acts like a fast version of self[key]=self.pop(key).
+
+        '''
         link = self.__map[key]
         link_prev = link[PREV]
         link_next = link[NEXT]
         link_prev[NEXT] = link_next
         link_next[PREV] = link_prev
         root = self.__root
-        last = root[PREV]
-        link[PREV] = last
-        link[NEXT] = root
-        last[NEXT] = root[PREV] = link
+        if last:
+            last = root[PREV]
+            link[PREV] = last
+            link[NEXT] = root
+            last[NEXT] = root[PREV] = link
+        else:
+            first = root[NEXT]
+            link[PREV] = root
+            link[NEXT] = first
+            root[NEXT] = first[PREV] = link
 
 
 ################################################################################

Modified: python/branches/py3k/Lib/functools.py
==============================================================================
--- python/branches/py3k/Lib/functools.py	(original)
+++ python/branches/py3k/Lib/functools.py	Mon Sep  6 23:26:09 2010
@@ -127,7 +127,7 @@
                             len=len, KeyError=KeyError):
         cache = OrderedDict()           # ordered least recent to most recent
         cache_popitem = cache.popitem
-        cache_renew = cache._renew
+        cache_renew = cache.move_to_end
         kwd_mark = object()             # separate positional and keyword args
         lock = Lock()
 

Modified: python/branches/py3k/Lib/test/test_collections.py
==============================================================================
--- python/branches/py3k/Lib/test/test_collections.py	(original)
+++ python/branches/py3k/Lib/test/test_collections.py	Mon Sep  6 23:26:09 2010
@@ -973,7 +973,19 @@
         od['a'] = 1
         self.assertEqual(list(od.items()), [('b', 2), ('a', 1)])
 
-
+    def test_move_to_end(self):
+        od = OrderedDict.fromkeys('abcde')
+        self.assertEqual(list(od), list('abcde'))
+        od.move_to_end('c')
+        self.assertEqual(list(od), list('abdec'))
+        od.move_to_end('c', 0)
+        self.assertEqual(list(od), list('cabde'))
+        od.move_to_end('c', 0)
+        self.assertEqual(list(od), list('cabde'))
+        od.move_to_end('e')
+        self.assertEqual(list(od), list('cabde'))
+        with self.assertRaises(KeyError):
+            od.move_to_end('x')
 
 class GeneralMappingTests(mapping_tests.BasicTestMappingProtocol):
     type2test = OrderedDict

Modified: python/branches/py3k/Misc/NEWS
==============================================================================
--- python/branches/py3k/Misc/NEWS	(original)
+++ python/branches/py3k/Misc/NEWS	Mon Sep  6 23:26:09 2010
@@ -13,6 +13,9 @@
 Library
 -------
 
+- collections.OrderedDict now supports a new method for repositioning
+  keys to either end.
+
 - Issue #9754: Similarly to assertRaises and assertRaisesRegexp, unittest
   test cases now also have assertWarns and assertWarnsRegexp methods to
   check that a given warning type was triggered by the code under test.


More information about the Python-checkins mailing list