[pypy-svn] r8627 - in pypy/dist/pypy/objspace/std: . test

adim at codespeak.net adim at codespeak.net
Thu Jan 27 11:08:44 CET 2005


Author: adim
Date: Thu Jan 27 11:08:44 2005
New Revision: 8627

Modified:
   pypy/dist/pypy/objspace/std/listobject.py
   pypy/dist/pypy/objspace/std/listtype.py
   pypy/dist/pypy/objspace/std/test/test_listobject.py
Log:
added key and reverse optional arguments to list.sort() (+tests)


Modified: pypy/dist/pypy/objspace/std/listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listobject.py	(original)
+++ pypy/dist/pypy/objspace/std/listobject.py	Thu Jan 27 11:08:44 2005
@@ -454,8 +454,9 @@
 #        CPython sort() should be studied to learn how
 #        to implement this functionality.
 
-def _partition(list, start, end, lt):
-    pivot = list[end]                          # Partition around the last value
+def _partition(list, key_list, start, end, lt):
+    pivot = list[end]
+    key_pivot = key_list[end]                          # Partition around the last value
     bottom = start-1                           # Start outside the area to be partitioned
     top = end                                  # Ditto
 
@@ -469,7 +470,8 @@
                 done = 1                       # ... we are done.
                 break
 
-            if lt(pivot, list[bottom]):        # Is the bottom out of place?
+            if lt(key_pivot, key_list[bottom]):        # Is the bottom out of place?
+                key_list[top] = key_list[bottom]
                 list[top] = list[bottom]       # Then put it at the top...
                 break                          # ... and start searching from the top.
 
@@ -480,19 +482,24 @@
                 done = 1                       # ... we are done.
                 break
 
-            if lt(list[top], pivot):           # Is the top out of place?
+            if lt(key_list[top], key_pivot):           # Is the top out of place?
+                key_list[bottom] = key_list[top]
                 list[bottom] = list[top]       # Then put it at the bottom...
                 break                          # ...and start searching from the bottom.
 
+    key_list[top] = key_pivot
     list[top] = pivot                          # Put the pivot in its place.
     return top                                 # Return the split point
 
 
-def _quicksort(list, start, end, lt):
+def _quicksort(list, key_list, start, end, lt):
+    """list is the list to be sorted
+    key_list is the list that will be used for comparisions
+    """
     if start < end:                            # If there are two or more elements...
-        split = _partition(list, start, end, lt)    # ... partition the sublist...
-        _quicksort(list, start, split-1, lt)        # ... and sort both halves.
-        _quicksort(list, split+1, end, lt)
+        split = _partition(list, key_list, start, end, lt)    # ... partition the sublist...
+        _quicksort(list, key_list, start, split-1, lt)        # ... and sort both halves.
+        _quicksort(list, key_list, split+1, end, lt)
 
 class Comparer:
     """Just a dumb container class for a space and a w_cmp, because
@@ -519,16 +526,28 @@
             raise
         return result < 0
 
-def list_sort__List_ANY(space, w_list, w_cmp):
+def list_sort__List_ANY_ANY_ANY(space, w_list, w_cmp, w_key, w_reverse):
     comparer = Comparer(space, w_cmp)
     if w_cmp is space.w_None:
         lt = comparer.simple_lt
     else:
         lt = comparer.complex_lt
-
+    # The key_list is the result of map(w_key, w_list), and will be
+    # used for comparisons during the qsort
+    if w_key is not space.w_None:
+        key_list = [space.call_function(w_key, item)
+                    for item in w_list.ob_item[:w_list.ob_size]]
+    else:
+        # If no key was specified, then comparison will be made on
+        # the original list
+        key_list = w_list.ob_item
     # XXX Basic quicksort implementation
     # XXX this is not stable !!
-    _quicksort(w_list.ob_item, 0, w_list.ob_size-1, lt)
+    _quicksort(w_list.ob_item, key_list, 0, w_list.ob_size-1, lt)
+    # _quicksort(w_list.ob_item, 0, w_list.ob_size-1, lt)
+    # reverse list if needed
+    if space.is_true(w_reverse):
+        list_reverse__List(space, w_list)
     return space.w_None
 
 

Modified: pypy/dist/pypy/objspace/std/listtype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/listtype.py	(original)
+++ pypy/dist/pypy/objspace/std/listtype.py	Thu Jan 27 11:08:44 2005
@@ -10,7 +10,7 @@
 list_index    = MultiMethod('index',  4, defaults=(0,maxint))
 list_count    = MultiMethod('count',  2)
 list_reverse  = MultiMethod('reverse',1)
-list_sort     = MultiMethod('sort',   2, defaults=(None,), argnames=['cmp'])
+list_sort     = MultiMethod('sort',   4, defaults=(None, None, False), argnames=['cmp', 'key', 'reverse'])
 list_reversed = MultiMethod('__reversed__', 1)
 
 def app_list_reversed__ANY(lst):

Modified: pypy/dist/pypy/objspace/std/test/test_listobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_listobject.py	(original)
+++ pypy/dist/pypy/objspace/std/test/test_listobject.py	Thu Jan 27 11:08:44 2005
@@ -313,6 +313,35 @@
         l = [ 'a' ]
         l.sort(lencmp)
         assert l == [ 'a' ]
+
+    def test_sort_key(self):
+        def lower(x): return x.lower()
+        l = ['a', 'C', 'b']
+        l.sort(key = lower)
+        assert l == ['a', 'b', 'C']
+        l = []
+        l.sort(key = lower)
+        assert l == []
+        l = [ 'a' ]
+        l.sort(key = lower)
+        assert l == [ 'a' ]
+        
+    def test_sort_reversed(self):
+        l = range(10)
+        l.sort(reverse = True)
+        assert l == range(9, -1, -1)
+        l = []
+        l.sort(reverse = True)
+        assert l == []
+        l = [1]
+        l.sort(reverse = True)
+        assert l == [1]
+
+    def test_sort_cmp_key_reverse(self):
+        def lower(x): return x.lower()
+        l = ['a', 'C', 'b']
+        l.sort(reverse = True, key = lower)
+        assert l == ['C', 'b', 'a']
         
     def test_extended_slice(self):
         l = range(10)



More information about the Pypy-commit mailing list