Python sort sorted 详解

来源:互联网 发布:技术狗python网盘 编辑:程序博客网 时间:2024/04/29 22:06

Sorting Basics

函数原型:sorted ( iterable,   key=None,   cmp=None,  reverse=False)

A simple ascending sort is very easy -- just call the sorted() function. It returns a new sorted list:

(简单的排序仅仅通过调用sorted函数即可,他返回一个新的排好序的列表

>>> sorted([5, 2, 3, 1, 4])[1, 2, 3, 4, 5]

You can also use the list.sort() method of a list. It modifies the list in-place (and returns None to avoid confusion). Usually it's less convenient than sorted() - but if you don't need the original list, it's slightly more efficient.

(你同样可以调用列表的sort方法,它对列表本身做修改排序(为了避免混乱,返回None)。通常它没有sorted方便,除非你不再需要原始的列表,sort更直接、高效)

>>> a = [5, 2, 3, 1, 4]>>> a.sort()>>> a[1, 2, 3, 4, 5]

Another difference is that the list.sort() method is only defined for lists. In contrast, the sorted() function accepts any iterable.

(另一个不同点是,list.sort()方法只对列表有效,与此对比,sorted()函数能接受所有可迭代对象

>>> sorted({1: 'D', 2: 'B', 3: 'B', 4: 'E', 5: 'A'})[1, 2, 3, 4, 5]

Key Functions

Starting with Python 2.4, both list.sort() and sorted() added a key parameter to specify a function to be called on each list element prior to making comparisons.

(从Python 2.4开始,list.sort() 和 sorted() 都添加了key参数用来指定对每个元素做比较的函数

For example, here's a case-insensitive string comparison:

>>> sorted("This is a test string from Andrew".split(), key=str.lower)['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

The value of the key parameter should be a function that takes a single argument and returns a key to use for sorting purposes. This technique is fast because the key function is called exactly once for each input record.

(key参数的值应该是一个只带一个参数并且返回一个用于排序的值得函数,这一技术是快速的,因为key函数只被每个输入调用一次

A common pattern is to sort complex objects using some of the object's indices as a key. For example:

>>> student_tuples = [        ('john', 'A', 15),        ('jane', 'B', 12),        ('dave', 'B', 10),]>>> sorted(student_tuples, key=lambda student: student[2])   # sort by age[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

The same technique works for objects with named attributes. For example:

>>> class Student:        def __init__(self, name, grade, age):                self.name = name                self.grade = grade                self.age = age        def __repr__(self):                return repr((self.name, self.grade, self.age))        def weighted_grade(self):                return 'CBA'.index(self.grade) / float(self.age)>>> student_objects = [        Student('john', 'A', 15),        Student('jane', 'B', 12),        Student('dave', 'B', 10),]>>> sorted(student_objects, key=lambda student: student.age)   # sort by age[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

Operator Module Functions

The key-function patterns shown above are very common, so Python provides convenience functions to make accessor functions easier and faster. The operator module has itemgetterattrgetter, and starting in Python 2.6 a methodcaller function.

(上面展示的key-function模式是非常通用的,Python还提供了方便的函数以使这些功能更加容易和快速。operator模块有itemgetter,attrgetter函数,已经Python 2.6 新增的methodcaller函数)

Using those functions, the above examples become simpler and faster.

(使用这些函数,上面的例子将变的更加简单和快速)

>>> from operator import itemgetter, attrgetter, methodcaller>>> sorted(student_tuples, key=itemgetter(2))[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]>>> sorted(student_objects, key=attrgetter('age'))[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

The operator module functions allow multiple levels of sorting. For example, to sort by grade then by age:

(operator模块函数运行对级别的排序。例如,通过grade和age排序)

>>> sorted(student_tuples, key=itemgetter(1,2))[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]>>> sorted(student_objects, key=attrgetter('grade', 'age'))[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]

The third function from the operator module, methodcaller is used in the following example in which the weighted grade of each student is shown before sorting on it:

(从operator模块导入的第三个函数-methodcaller,将在接下来的例子中用来对每个学生排序前计算加权成绩)

>>> [(student.name, student.weighted_grade()) for student in student_objects][('john', 0.13333333333333333), ('jane', 0.08333333333333333), ('dave', 0.1)]>>> sorted(student_objects, key=methodcaller('weighted_grade'))[('jane', 'B', 12), ('dave', 'B', 10), ('john', 'A', 15)]

Ascending and Descending

Both list.sort() and sorted() accept a reverse parameter with a boolean value. This is using to flag descending sorts. For example, to get the student data in reverse age order:

(list.sort() 和 sorted() 函数都接受一个reverse布尔值参数,这将用来标记排序结果的顺序。例如,让student数据按年龄降序排列)

>>> sorted(student_tuples, key=itemgetter(2), reverse=True)[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]>>> sorted(student_objects, key=attrgetter('age'), reverse=True)[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]

Sort Stability and Complex Sorts

Starting with Python 2.2, sorts are guaranteed to be stable. That means that when multiple records have the same key, their original order is preserved.

(从Python 2.2开始, sorts保证是稳定的。这就意味着,当多个记录拥有相同的key, 他们将按原始顺序保存)

>>> data = [('red', 1), ('blue', 1), ('red', 2), ('blue', 2)]>>> sorted(data, key=itemgetter(0))[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]

Notice how the two records for 'blue' retain their original order so that ('blue', 1) is guaranteed to precede ('blue', 2).

This wonderful property lets you build complex sorts in a series of sorting steps. For example, to sort the student data by descending grade and then ascending age, do the age sort first and then sort again using grade:

(注意观察这两个包含‘blue’的记录是如何保持他们的原始顺序以至于(‘blue’, 1)保证在(‘blue’, 2)前面。这是有趣的属性,通过它能让你通过一系列排序步奏构建复杂的排序。例如,让student数据按grade降序然后按age升序排序,先按age排序,然后再按grade排序)(后面的先排序

>>> s = sorted(student_objects, key=attrgetter('age'))     # sort on secondary key>>> sorted(s, key=attrgetter('grade'), reverse=True)       # now sort on primary key, descending[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

The Old Way Using the cmp Parameter(老方法使用cmp参数排序)

Many constructs given in this HOWTO assume Python 2.4 or later. Before that, there was no sorted() builtin and list.sort() took no keyword arguments. Instead, all of the Py2.x versions supported a cmp parameter to handle user specified comparison functions.

In Py3.0, the cmp parameter was removed entirely (as part of a larger effort to simplify and unify the language, eliminating the conflict between rich comparisons and the__cmp__ methods).

In Py2.x, sort allowed an optional function which can be called for doing the comparisons. That function should take two arguments to be compared and then return a negative value for less-than, return zero if they are equal, or return a positive value for greater-than. For example, we can do:

(在这个介绍中给出的结构是假设你使用的是Python2.4或更高的版本。在那之前,Python里没有提供sorted()内建函数,list.sort()没有key,reverse关键字参数。作为替代,所有Python 2.x版本中都支持cmp参数用来支持用户自定义比较函数。

在Py3.0, cmp参数被彻底删除了(作为努力简化和统一语言以及消除丰富的比较函数和__cmp__方法的一部分)。

>>> def numeric_compare(x, y):        return x - y>>> sorted([5, 2, 4, 1, 3], cmp=numeric_compare)[1, 2, 3, 4, 5]

Or you can reverse the order of comparison with:

>>> def reverse_numeric(x, y):        return y - x>>> sorted([5, 2, 4, 1, 3], cmp=reverse_numeric)[5, 4, 3, 2, 1]
                                             
0 0
原创粉丝点击