在Python中讨论"排序"函数

Jer*_*amu 0 python sorting

我知道Python中的sorted()函数可以在数字列表或字典上运行,并返回已排序的数字或键的列表.例如:

w = [1,4,6,8,2,0,3,2]
sorted(w)
Run Code Online (Sandbox Code Playgroud)

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

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

Mic*_*nas 10

Python的sorted发生在任何迭代(list,dict,tuple),例如,

>>> 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
Run Code Online (Sandbox Code Playgroud)

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

>>> sorted(['hello', 'foo', 'bar'], key=str.lower)
['bar', 'foo', 'hello']
>>> sorted(['hello', 'foo', 'bar'], key=len)
['foo', 'bar', 'hello']
Run Code Online (Sandbox Code Playgroud)

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

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

这也适用于元组:

>>> 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)]
Run Code Online (Sandbox Code Playgroud)

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

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

>>> 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>]
Run Code Online (Sandbox Code Playgroud)

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

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

此外,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>]
Run Code Online (Sandbox Code Playgroud)

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

>>> sorted([3,4,7,2,1], reverse=True)
[7, 4, 3, 2, 1]
Run Code Online (Sandbox Code Playgroud)

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']
Run Code Online (Sandbox Code Playgroud)

注意:多种类型之间的排序并没有出现在Python 3的工作,你会得到一个TypeError.

最后,由于历史原因,Python sorted允许使用a cmp或比较函数.例如:

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

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

资料来源: