在Python中讨论“排序”函数

时间:2015-04-18 21:00:40

标签: python sorting

我知道Python中的sorted()函数可以对数字列表或字典进行操作,并返回已排序的数字或键的列表。例如:

w = [1,4,6,8,2,0,3,2]
sorted(w)

然后我们可以获得重新排列的排序数字列表为[0,1,2,2,3,4,6,8]

我的问题是:sorted()函数有没有其他功能?我希望你们能给我一些简单的例子。 :)

1 个答案:

答案 0 :(得分:10)

Python的sorted接受任何可迭代的(listdicttuple),例如,

>>> sorted([3,4,2,5]) # list
[2, 3, 4, 5]
>>> sorted({1: 'hello', 2: 'there', 4: 'foo', 3: 'bar'}) # dict
[1, 2, 3, 4]
>>> sorted(('Foo', 'Bar', 'Baz')) # tuple

此外,它可以选择接受key,这意味着您可以按某种特征进行排序。例如,您可以按字母顺序或按字典顺序对字符串进行排序:

>>> sorted(['hello', 'foo', 'bar'], key=str.lower)
['bar', 'foo', 'hello']
>>> sorted(['hello', 'foo', 'bar'], key=len)
['foo', 'bar', 'hello']

使用给定key进行排序的一个很酷的功能意味着您还可以提供lambda表达式,因此,如下例所示,您可以按字典值(列表)的长度排序:

>>> x = { 1: ['a', 'b', 'c'], 2: ['d'], 3: ['e', 'f'] }
>>> sorted( x, key=lambda k: len(x[k]) )
[2, 3, 1]

这也适用于元组:

>>> x = [('foo', 3, 2), ('bar', 1, 4), ('baz', 4, 1)]
>>> sorted(x, key=lambda k: k[1])
[('bar', 1, 4), ('foo', 3, 2), ('baz', 4, 1)]

请注意,在对嵌套的listtuple s(或其他迭代)进行排序时,它将首先按第一个内部索引排序,然后按后续内部索引排序。

您还可以指定要对类进行排序的方式:

>>> class Foo(object):
...     def __init__(self, name, age):
...         self.name = name
...         self.age = age
...     def __repr__(self): # this will help us recognize our objs after we've sorted
...         return "<name: {name}, age: {age}>".format(name=self.name, age=self.age)
>>> f = Foo('Bar', 3)
>>> g = Foo('Baz', 4)
>>> def byAge(foo): return foo.age
>>> sorted([f, g], key=byAge)
[<name: Bar, age: 3>, <name: Baz, age: 4>]

您还可以使用attrgetter获取对象的属性来指定要排序的内容:

>>> from operator import attrgetter
>>> sorted([f, g], key=attrgetter('age'))
[<name: Bar, age: 3>, <name: Baz, age: 4>]

此外,使用key,您可以拥有一个组合多个键的功能,例如

>>> class Foo(object):
...     def __init__(self, name, age, years_programming):
...         self.name = name
...         self.age = age
...         self.years_programming = years_programming
...     def __repr__(self): # this will help us recognize our objs after we've sorted
...         return "<name: {name}, age: {age}, years_prog: {years}>".format(name=self.name, age=self.age, years=self.years_programming)
>>> f = Foo('Bar', 3, 1)
>>> g = Foo('Baz', 4, 3)
>>> h = Foo('John', 10, 0)
>>> def by_years_experience(foo):
...     return foo.age * foo.years_programming
>>> sorted([f, g, h], key=by_years_experience)
[<name: John, age: 10, years_prog: 0>, <name: Bar, age: 3, years_prog: 1>, <name: Baz, age: 4, years_prog: 3>]

接下来,您可以指定是否需要反向排序:

>>> sorted([3,4,7,2,1], reverse=True)
[7, 4, 3, 2, 1]

sorted也适用于多种类型的列表(仅在Python 2中):

>>> a = [('hello', 1, 2), ['foo', 5, 3], {0: 'bar', 1: 'baz'}]
>>> sorted(a)
[{0: 'bar', 1: 'baz'}, ['foo', 5, 3], ('hello', 1, 2)]
>>> sorted(a, key=lambda x: x[1])
[('hello', 1, 2), ['foo', 5, 3], {0: 'bar', 1: 'baz'}]
>>> b = ['hello', 1, 3]
>>> sorted(b)
[1, 3, 'hello']

注意:在多种类型之间进行排序在Python 3中工作。您将获得TypeError

最后,由于历史原因,Python的sorted允许cmp或比较功能。例如:

>>> def reverse_numeric(x, y):
...     return y - x
>>> sorted([3,4,7,2,1], cmp=reverse_numeric)
[7, 4, 3, 2, 1]

应该注意的是,Python sorted使用Timsort作为排序算法,stable sort。这意味着如果存在多个相同的元素(或字段),则将保留原始顺序。

来源: