-
1 # 則淨
-
2 # 被Python迷倒的大饞貓
Python list內建sort()方法用來排序,也可以用p全域性sorted()方法來對可迭代的序列排序生成新的序列,也可以使用operator模組。下面將詳細說明:
1)排序基礎
簡單的升序排序是非常容易的。只需要呼叫sorted()方法。它返回一個新的list,新的list的元素基於小於運算子(__lt__)來排序。
>>> sorted([5, 2, 3, 1, 4])
[1, 2, 3, 4, 5]
也可以使用list.sort()方法來排序,此時list本身將被修改。通常此方法不如sorted()方便,但是如果你不需要保留原來的list,此方法將更有效。
>>> a = [5, 2, 3, 1, 4]
>>> a.sort()
>>> a
[1, 2, 3, 4, 5]
另一個不同就是list.sort()方法僅被定義在list中,相反地sorted()方法對所有的可迭代序列都有效。
sorted({1: "D", 2: "B", 3: "B", 4: "E", 5: "A"})
[1, 2, 3, 4, 5]
2)key引數/函式
從python2.4開始,list.sort()和sorted()函式增加了key引數來指定一個函式,此函式將在每個元素比較前被呼叫。 例如透過key指定的函式來忽略字串的大小寫:
>>> sorted("This is a test string from Andrew".split(), key=str.lower)
["a", "Andrew", "from", "is", "string", "test", "This"]
key引數的值為一個函式,此函式只有一個引數且返回一個值用來進行比較。這個技術是快速的因為key指定的函式將準確地對每個元素呼叫。
更廣泛的使用情況是用複雜物件的某些值來對複雜物件的序列排序,例如:
>>> 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)]
同樣的技術對擁有命名屬性的複雜物件也適用,例如:
>>> 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))
>>> 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)]
3)升序和降序
list.sort()和sorted()都接受一個引數reverse(True or False)來表示升序或降序排序。例如對上面的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)]
4)排序的穩定性和複雜排序
從python2.2開始,排序被保證為穩定的。意思是說多個元素如果有相同的key,則排序前後他們的先後順序不變。
>>> data = [("red", 1), ("blue", 1), ("red", 2), ("blue", 2)]
>>> sorted(data, key=itemgetter(0))
[("blue", 1), ("blue", 2), ("red", 1), ("red", 2)]
注意在排序後"blue"的順序被保持了,即"blue", 1在"blue", 2的前面。
更復雜地你可以構建多個步驟來進行更復雜的排序,例如對student資料先以grade降序排列,然後再以age升序排列。
>>> 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)]
另外,Operator 模組函式
上面的key引數的使用非常廣泛,因此python提供了一些方便的函式來使得訪問方法更加容易和快速。operator模組有itemgetter,attrgetter,從2.6開始還增加了methodcaller方法。使用這些方法,上面的操作將變得更加簡潔和快速:
>>> from operator import itemgetter, attrgetter
>>> 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)]
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)]
回覆列表
>>>a = [5,7,6,3,4,1,2]
>>> b = sorted(a) # 保留原列表
>>> a [5, 7, 6, 3, 4, 1, 2]
>>> b[1, 2, 3, 4, 5, 6, 7]
如上,這樣就用排序函式對列表進行了排序。
>>> students = [("john", "A", 15), ("jane", "B", 12), ("dave", "B", 10)]
>>> sorted(students, key=lambda s: s[2]) # 按年齡排序[("dave", "B", 10), ("jane", "B", 12), ("john", "A", 15)]
>>> sorted(students, key=lambda s: s[2], reverse=True) # 按降序[("john", "A", 15), ("jane", "B", 12), ("dave", "B", 10)]
>>>
如上,可以按照升序跟降序進行排序。
請參考。