]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Add method to OrderedDict for repositioning keys to the ends.
authorRaymond Hettinger <python@rcn.com>
Mon, 6 Sep 2010 21:26:09 +0000 (21:26 +0000)
committerRaymond Hettinger <python@rcn.com>
Mon, 6 Sep 2010 21:26:09 +0000 (21:26 +0000)
Doc/library/collections.rst
Lib/collections.py
Lib/functools.py
Lib/test/test_collections.py
Misc/NEWS

index 454817b7aa42a8919fe5f364ad8759413bfbc76b..1cc4097b6f829f9eae51c1398db6902764c0cd87 100644 (file)
@@ -793,6 +793,23 @@ the items are returned in the order their keys were first added.
       (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`.
 
index c3c51d120fa0f03aaedf08a951c11b22945668a8..00886ef06ebf5b7b601a9e723b81edf92d656ae8 100644 (file)
@@ -173,18 +173,29 @@ class OrderedDict(dict, MutableMapping):
     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
 
 
 ################################################################################
index b2df390529e3e3c67c645fec4e767b62680c3d12..a723f66a3c5893ae74a7c4710535e98e645270a6 100644 (file)
@@ -127,7 +127,7 @@ def lru_cache(maxsize=100):
                             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()
 
index 75d660d6287915986d8a71ef651f06c5ae254719..7beb061b2f4d48a64acba528aadc56d7db54fb95 100644 (file)
@@ -973,7 +973,19 @@ class TestOrderedDict(unittest.TestCase):
         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
index d2d35d05da72a95f48b8fab6649476e4eb918055..262983b31378cc66b02ecb0bc5786c1b44bd8af8 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -13,6 +13,9 @@ Core and Builtins
 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.