mirror of
https://github.com/python/cpython.git
synced 2025-09-10 02:36:56 +00:00
Add list.sorted() classmethod.
This commit is contained in:
parent
c43a7e7c37
commit
0a9b9da0c3
5 changed files with 113 additions and 6 deletions
|
@ -629,7 +629,7 @@ there is at least one character, false otherwise.
|
||||||
|
|
||||||
\begin{methoddesc}[string]{istitle}{}
|
\begin{methoddesc}[string]{istitle}{}
|
||||||
Return true if the string is a titlecased string and there is at least one
|
Return true if the string is a titlecased string and there is at least one
|
||||||
character, i.e. uppercase characters may only follow uncased
|
character, for example uppercase characters may only follow uncased
|
||||||
characters and lowercase characters only cased ones. Return false
|
characters and lowercase characters only cased ones. Return false
|
||||||
otherwise.
|
otherwise.
|
||||||
\end{methoddesc}
|
\end{methoddesc}
|
||||||
|
@ -975,6 +975,9 @@ The following operations are defined on mutable sequence types (where
|
||||||
\lineiii{\var{s}.sort(\optional{\var{cmp}=None\optional{, \var{key}=None
|
\lineiii{\var{s}.sort(\optional{\var{cmp}=None\optional{, \var{key}=None
|
||||||
\optional{, \var{reverse}=False}}})}
|
\optional{, \var{reverse}=False}}})}
|
||||||
{sort the items of \var{s} in place}{(7), (8), (9), (10)}
|
{sort the items of \var{s} in place}{(7), (8), (9), (10)}
|
||||||
|
\lineiii{\var{s}.sorted(\var{iterable}\optional{, \var{cmp}=None\optional{, \var{key}=None
|
||||||
|
\optional{, \var{reverse}=False}}})}
|
||||||
|
{return a new sorted list from the items in \var{iterable}}{(8), (9), (11)}
|
||||||
\end{tableiii}
|
\end{tableiii}
|
||||||
\indexiv{operations on}{mutable}{sequence}{types}
|
\indexiv{operations on}{mutable}{sequence}{types}
|
||||||
\indexiii{operations on}{sequence}{types}
|
\indexiii{operations on}{sequence}{types}
|
||||||
|
@ -1024,8 +1027,8 @@ Notes:
|
||||||
list. To remind you that they operate by side effect, they don't return
|
list. To remind you that they operate by side effect, they don't return
|
||||||
the sorted or reversed list.
|
the sorted or reversed list.
|
||||||
|
|
||||||
\item[(8)] The \method{sort()} method takes optional arguments for
|
\item[(8)] The \method{sort()} and \method{sorted()} methods take optional
|
||||||
controlling the comparisions.
|
arguments for controlling the comparisions.
|
||||||
|
|
||||||
\var{cmp} specifies a custom comparison function of two arguments
|
\var{cmp} specifies a custom comparison function of two arguments
|
||||||
(list items) which should return a negative, zero or positive number
|
(list items) which should return a negative, zero or positive number
|
||||||
|
@ -1052,7 +1055,8 @@ Notes:
|
||||||
\versionchanged[Support for \var{key} and \var{reverse} was added]{2.4}
|
\versionchanged[Support for \var{key} and \var{reverse} was added]{2.4}
|
||||||
|
|
||||||
\item[(9)] Starting with Python 2.3, the \method{sort()} method is
|
\item[(9)] Starting with Python 2.3, the \method{sort()} method is
|
||||||
guaranteed to be stable. A sort is stable if it guarantees not to
|
guaranteed to be stable. Starting with Python 2.4, the \method{sorted()}
|
||||||
|
method is also guaranteed to be stable. A sort is stable if it does not
|
||||||
change the relative order of elements that compare equal --- this is
|
change the relative order of elements that compare equal --- this is
|
||||||
helpful for sorting in multiple passes (for example, sort by
|
helpful for sorting in multiple passes (for example, sort by
|
||||||
department, then by salary grade).
|
department, then by salary grade).
|
||||||
|
@ -1062,6 +1066,9 @@ Notes:
|
||||||
of Python 2.3 makes the list appear empty for the duration, and raises
|
of Python 2.3 makes the list appear empty for the duration, and raises
|
||||||
\exception{ValueError} if it can detect that the list has been
|
\exception{ValueError} if it can detect that the list has been
|
||||||
mutated during a sort.
|
mutated during a sort.
|
||||||
|
|
||||||
|
\item[(11)] \method{sorted()} is a class method that returns a new list.
|
||||||
|
\versionadded{2.4}
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,11 @@ class UserList:
|
||||||
def index(self, item, *args): return self.data.index(item, *args)
|
def index(self, item, *args): return self.data.index(item, *args)
|
||||||
def reverse(self): self.data.reverse()
|
def reverse(self): self.data.reverse()
|
||||||
def sort(self, *args, **kwds): self.data.sort(*args, **kwds)
|
def sort(self, *args, **kwds): self.data.sort(*args, **kwds)
|
||||||
|
def sorted(cls, iterable, *args, **kwds):
|
||||||
|
s = cls(iterable)
|
||||||
|
s.sort(*args, **kwds)
|
||||||
|
return s
|
||||||
|
sorted = classmethod(sorted)
|
||||||
def extend(self, other):
|
def extend(self, other):
|
||||||
if isinstance(other, UserList):
|
if isinstance(other, UserList):
|
||||||
self.data.extend(other.data)
|
self.data.extend(other.data)
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from test.test_support import verbose
|
from test.test_support import verbose
|
||||||
import random
|
import random
|
||||||
|
from UserList import UserList
|
||||||
|
from sets import Set
|
||||||
|
|
||||||
nerrors = 0
|
nerrors = 0
|
||||||
|
|
||||||
|
@ -190,6 +192,7 @@ class TestDecorateSortUndecorate(unittest.TestCase):
|
||||||
random.shuffle(data)
|
random.shuffle(data)
|
||||||
data.sort(reverse=True)
|
data.sort(reverse=True)
|
||||||
self.assertEqual(data, range(99,-1,-1))
|
self.assertEqual(data, range(99,-1,-1))
|
||||||
|
self.assertRaises(TypeError, data.sort, "wrong type")
|
||||||
|
|
||||||
def test_reverse_stability(self):
|
def test_reverse_stability(self):
|
||||||
data = [(random.randrange(100), i) for i in xrange(200)]
|
data = [(random.randrange(100), i) for i in xrange(200)]
|
||||||
|
@ -201,11 +204,66 @@ class TestDecorateSortUndecorate(unittest.TestCase):
|
||||||
copy2.sort(key=lambda x: x[0], reverse=True)
|
copy2.sort(key=lambda x: x[0], reverse=True)
|
||||||
self.assertEqual(data, copy2)
|
self.assertEqual(data, copy2)
|
||||||
|
|
||||||
|
class TestSorted(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_basic(self):
|
||||||
|
data = range(100)
|
||||||
|
copy = data[:]
|
||||||
|
random.shuffle(copy)
|
||||||
|
self.assertEqual(data, list.sorted(copy))
|
||||||
|
self.assertNotEqual(data, copy)
|
||||||
|
|
||||||
|
data.reverse()
|
||||||
|
random.shuffle(copy)
|
||||||
|
self.assertEqual(data, list.sorted(copy, cmp=lambda x, y: cmp(y,x)))
|
||||||
|
self.assertNotEqual(data, copy)
|
||||||
|
random.shuffle(copy)
|
||||||
|
self.assertEqual(data, list.sorted(copy, key=lambda x: -x))
|
||||||
|
self.assertNotEqual(data, copy)
|
||||||
|
random.shuffle(copy)
|
||||||
|
self.assertEqual(data, list.sorted(copy, reverse=1))
|
||||||
|
self.assertNotEqual(data, copy)
|
||||||
|
|
||||||
|
def test_inputtypes(self):
|
||||||
|
s = 'abracadabra'
|
||||||
|
for T in [unicode, list, tuple]:
|
||||||
|
self.assertEqual(list.sorted(s), list.sorted(T(s)))
|
||||||
|
|
||||||
|
s = ''.join(dict.fromkeys(s).keys()) # unique letters only
|
||||||
|
for T in [unicode, Set, list, tuple, dict.fromkeys]:
|
||||||
|
self.assertEqual(list.sorted(s), list.sorted(T(s)))
|
||||||
|
|
||||||
|
def test_baddecorator(self):
|
||||||
|
data = 'The quick Brown fox Jumped over The lazy Dog'.split()
|
||||||
|
self.assertRaises(TypeError, list.sorted, data, None, lambda x,y: 0)
|
||||||
|
|
||||||
|
def classmethods(self):
|
||||||
|
s = "hello world"
|
||||||
|
a = list.sorted(s)
|
||||||
|
b = UserList.sorted(s)
|
||||||
|
c = [].sorted(s)
|
||||||
|
d = UserList().sorted(s)
|
||||||
|
class Mylist(list):
|
||||||
|
def __new__(cls):
|
||||||
|
return UserList()
|
||||||
|
e = MyList.sorted(s)
|
||||||
|
f = MyList().sorted(s)
|
||||||
|
class Myuserlist(UserList):
|
||||||
|
def __new__(cls):
|
||||||
|
return []
|
||||||
|
g = MyList.sorted(s)
|
||||||
|
h = MyList().sorted(s)
|
||||||
|
self.assert_(a == b == c == d == e == f == g == h)
|
||||||
|
self.assert_(b.__class__ == d.__class__ == UserList)
|
||||||
|
self.assert_(e.__class__ == f.__class__ == MyList)
|
||||||
|
self.assert_(g.__class__ == h.__class__ == Myuserlist)
|
||||||
|
|
||||||
#==============================================================================
|
#==============================================================================
|
||||||
|
|
||||||
def test_main(verbose=None):
|
def test_main(verbose=None):
|
||||||
test_classes = (
|
test_classes = (
|
||||||
TestDecorateSortUndecorate,
|
TestDecorateSortUndecorate,
|
||||||
|
TestSorted,
|
||||||
TestBugs,
|
TestBugs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@ Core and builtins
|
||||||
starting with Py2.3 are guaranteed to be stable (the relative order of
|
starting with Py2.3 are guaranteed to be stable (the relative order of
|
||||||
records with equal keys is unchanged).
|
records with equal keys is unchanged).
|
||||||
|
|
||||||
- Added a list.copysort() method that returns a copy of the sorted list
|
- Added a list.sorted() classmethod that returns a new sorted list
|
||||||
while leaving the original intact.
|
from any iterable.
|
||||||
|
|
||||||
- Added test whether wchar_t is signed or not. A signed wchar_t is not
|
- Added test whether wchar_t is signed or not. A signed wchar_t is not
|
||||||
usable as internal unicode type base for Py_UNICODE since the
|
usable as internal unicode type base for Py_UNICODE since the
|
||||||
|
|
|
@ -2000,6 +2000,38 @@ PyList_Sort(PyObject *v)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
listsorted(PyObject *cls, PyObject *args, PyObject *kwds)
|
||||||
|
{
|
||||||
|
PyObject *newlist, *v, *seq, *compare=NULL, *keyfunc=NULL, *newargs;
|
||||||
|
static char *kwlist[] = {"iterable", "cmp", "key", "reverse", 0};
|
||||||
|
long reverse;
|
||||||
|
|
||||||
|
if (args != NULL) {
|
||||||
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOi:sorted",
|
||||||
|
kwlist, &seq, &compare, &keyfunc, &reverse))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
newlist = PyObject_CallFunctionObjArgs(cls, seq, NULL);
|
||||||
|
if (newlist == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
newargs = PyTuple_GetSlice(args, 1, 4);
|
||||||
|
if (newargs == NULL) {
|
||||||
|
Py_DECREF(newlist);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
v = listsort((PyListObject *)newlist, newargs, kwds);
|
||||||
|
Py_DECREF(newargs);
|
||||||
|
if (v == NULL) {
|
||||||
|
Py_DECREF(newlist);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_DECREF(v);
|
||||||
|
return newlist;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
listreverse(PyListObject *self)
|
listreverse(PyListObject *self)
|
||||||
{
|
{
|
||||||
|
@ -2335,6 +2367,9 @@ PyDoc_STRVAR(reverse_doc,
|
||||||
PyDoc_STRVAR(sort_doc,
|
PyDoc_STRVAR(sort_doc,
|
||||||
"L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;\n\
|
"L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;\n\
|
||||||
cmp(x, y) -> -1, 0, 1");
|
cmp(x, y) -> -1, 0, 1");
|
||||||
|
PyDoc_STRVAR(sorted_doc,
|
||||||
|
"list.sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list;\n\
|
||||||
|
cmp(x, y) -> -1, 0, 1");
|
||||||
|
|
||||||
static PyMethodDef list_methods[] = {
|
static PyMethodDef list_methods[] = {
|
||||||
{"append", (PyCFunction)listappend, METH_O, append_doc},
|
{"append", (PyCFunction)listappend, METH_O, append_doc},
|
||||||
|
@ -2346,6 +2381,8 @@ static PyMethodDef list_methods[] = {
|
||||||
{"count", (PyCFunction)listcount, METH_O, count_doc},
|
{"count", (PyCFunction)listcount, METH_O, count_doc},
|
||||||
{"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc},
|
{"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc},
|
||||||
{"sort", (PyCFunction)listsort, METH_VARARGS | METH_KEYWORDS, sort_doc},
|
{"sort", (PyCFunction)listsort, METH_VARARGS | METH_KEYWORDS, sort_doc},
|
||||||
|
{"sorted", (PyCFunction)listsorted,
|
||||||
|
METH_VARARGS | METH_KEYWORDS | METH_CLASS, sorted_doc},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue