1. 程式人生 > >python 中的sort ()和sorted()

python 中的sort ()和sorted()

原文

list.sort()

list的一個方法,具有三個引數:cmp,key,reverse(Python3只有後兩個)
一個list呼叫sort方法後,對該list進行排序,不儲存原list

引數解釋:

cmp(僅支援Python2) : 比較函式,可以自定義,如cmp = lambda x,y:y-x; cmp = cmp(x,y)
key : 排序關鍵字,值為一個函式,此函式只有一個引數且返回一個值,比如,有一個User物件的list,希望通過物件的 user_id 屬性進行排序,可以提供一個以 User 例項作為輸入並輸出對應 user_id 值的函式給 key(即key = lambda u:u.user_id 或 key=attrgetter(‘user_id’))
reverse : 預設為False,為True的話就是反序排序
呼叫方法:

#一般序列
# 1.數字序列
>>> L = [5,2,3,1,4]
>>> L
[5, 2, 3, 1, 4]
>>> L.sort()
>>> L
[1, 2, 3, 4, 5]
>>> L.sort(reverse=True)
>>> L
[5, 4, 3, 2, 1]
# 2.字串序列
>>> StrList = ['Smooth', 'is', 'fast', 'Fast', 'is', 'smooth']
>>> StrList
['Smooth'
, 'is', 'fast', 'Fast', 'is', 'smooth'] # 2.1一般字典序排列 >>> StrList.sort() >>> StrList ['Fast', 'Smooth', 'fast', 'is', 'is', 'smooth'] # 2.2忽略大小寫 >>> StrList.sort(key = str.lower) >>> StrList ['Fast', 'fast', 'is', 'is', 'Smooth', 'smooth'] # 2.3按照字串長度排序 >>>
StrList.sort(key = len) >>> StrList ['is', 'is', 'Fast', 'fast', 'Smooth', 'smooth'] >>> StrList.sort(key = len, reverse = True) >>> StrList ['Smooth', 'smooth', 'Fast', 'fast', 'is', 'is']

關於cmp函式的補充

在Python2版本中,存在cmp引數,可以自定義比較函式,如:

#Python 2.7.6
>>> Num = list(xrange(10))
>>> Num
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> Num.sort(cmp=lambda x,y:y-x)
>>> Num
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

在Python3中,cmp引數與內建函式cmp()被一併移除,自定義比較函式通過key=func來實現(其實是通過key來定義每一個元素的關鍵字編碼值)。這是因為Python3中不同型別間的比較不再依賴於固定跨型別排序,對不同型別的元素進行排序,首先要將不同型別元素轉換為相同型別的編碼值,然後才能進行升降排序。

比如一個列表中有不同型別的元素:

#Python 2.7.6
>>> L = [2,3,3.5,'dd','-5','蛤蛤']
>>> L.sort()
>>> L
[2, 3, 3.5, '-5', 'dd', '\xe8\x9b\xa4\xe8\x9b\xa4']

由於事先定義了固定的順序,在Python2中,對含有不同型別元素的List呼叫sort方法是允許的。
而在Python3中就會引發一個異常:

# Python 3.4.3
>>> L = [2,3,3.5,'dd','-5','蛤蛤']
>>> L
[2, 3, 3.5, 'dd', '-5', '蛤蛤']
>>> L.sort()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() < float()

我們只能把不同元素的關鍵字編碼值設為一致,例如字典序。

>>> L.sort(key=str)
>>> L
['-5', 2, 3, 3.5, 'dd', '蛤蛤']

sorted()

Python的一個內建函式,使用方法與list.sort()大體一致,不同在於兩個地方:

sorted(L)返回一個排序後的L,不改變原始的L;L.sort()是對原始的L進行操作,呼叫後原始的L會改變,沒有返回值。【所以a = a.sort()是錯的啦!a = sorted(a)才對!

sorted()適用於任何可迭代容器,list.sort()僅支援list(本身就是list的一個方法)

基於以上兩點,sorted使用頻率比list.sort()更高些,所以Python中更高階的排序技巧便通過sorted()來演示。

函式原型:
sorted(iterable, key=None, reverse=False) –> new sorted list

list與tuple
list與tuple排序方法與list.sort()大體一致,只不過sorted()不改變原結構:

#list
>>> Num
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a = sorted(Num, reverse=True)
>>> a
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> Num
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>>

#tuple
>>> Num
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)
>>> b = sorted(Num, reverse=True)
>>> b
[15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> Num
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15)

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

字典排序

1.sorted函式按key值對字典排序

先來基本介紹一下sorted函式,sorted(iterable,key,reverse),sorted一共有iterable,key,reverse這三個引數。

其中iterable表示可以迭代的物件,例如可以是dict.items()、dict.keys()等,key是一個函式,用來選取參與比較的元素,reverse則是用來指定排序是倒序還是順序,reverse=true則是倒序,reverse=false時則是順序,預設時reverse=false。

要按key值對字典排序,則可以使用如下語句:
a = {"a":2, "b":3, "c":0}
b = sorted(a.values())
c = sorted(a.keys())
print(b, c)#結果均為列表
直接使用sorted(d.keys())就能按key值對字典排序,這裡是按照順序對key值排序的,如果想按照倒序排序的話,則只要將reverse置為true即可。

2.sorted函式按value值對字典排序

要對字典的value排序則需要用到key引數,在這裡主要提供一種使用lambda表示式的方法,如下:
a = {"a":2, "b":3, "c":0}
b = sorted(a.items(), key= lambda x:x[1], reverse=True)#reverse=True降序
print(b)
print(dict(b))#b為元組元素組成的列表。重新轉換成字典。

這裡的d.items()實際上是將d轉換為可迭代物件,迭代物件的元素為(‘a’,2)、(‘b’,3)、(‘c’,0),items()方法將字典的元素轉化為了元組,而這裡key引數對應的lambda表示式的意思則是選取元組中的第二個元素作為比較引數(如果寫作key=lambda item:item[0]的話則是選取第一個元素作為比較物件,也就是key值作為比較物件。lambda x:y中x表示輸出引數,y表示lambda函式的返回值),所以採用這種方法可以對字典的value進行排序。注意排序後的返回值是一個list,而原字典中的名值對被轉換為了list中的元組。
先引一些資料

Operator 模組函式
由於 key 引數比較常用,所以 Python 內建了一些用來簡單、快速生成相關函式的方法, operator 模組提供了 itemgetter,attrgetter, 以及從 Python 2.6 開始提供的 methodcaller 函式。

itemgetter(item, …) –> itemgetter object

Return a callable object that fetches the given item(s) from its operand. 
After f = itemgetter(2), the call f(r) returns r[2]. 
After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])

簡單來說【個人理解】,就是按照索引順序返回訪問第i個物件的函式指標(從0開始)

>>> id
{'A': '0002', 'D': '0001', 'B': '0003', 'C': '0004'}
# sort by first item
>>> sorted(id.items(), key=itemgetter(0))
[('A', '0002'), ('B', '0003'), ('C', '0004'), ('D', '0001')]
# sort by second item
>>> sorted(id.items(), key=itemgetter(1))
[('D', '0001'), ('A', '0002'), ('B', '0003'), ('C', '0004')]

由於itemgetter()可以傳入多個item,這就使得多關鍵字排序簡單了許多:

>>> Stu = [('A','male','1994-11-19'),('B','female','1995-02-08'),('D','male','1996-03-14'),('C','female','1990-05-29')]
# sort by name
>>> sorted(Stu,key=itemgetter(0))
[('A', 'male', '1994-11-19'), ('B', 'female', '1995-02-08'), ('C', 'female', '1990-05-29'), ('D', 'male', '1996-03-14')]
# sort by sex
>>> sorted(Stu,key=itemgetter(1))
[('B', 'female', '1995-02-08'), ('C', 'female', '1990-05-29'), ('A', 'male', '1994-11-19'), ('D', 'male', '1996-03-14')]
# sort by name and sex
>>> sorted(Stu,key=itemgetter(0,1))
[('A', 'male', '1994-11-19'), ('B', 'female', '1995-02-08'), ('C', 'female', '1990-05-29'), ('D', 'male', '1996-03-14')]
# sort by sex and name
>>> sorted(Stu,key=itemgetter(1,0))
[('B', 'female', '1995-02-08'), ('C', 'female', '1990-05-29'), ('A', 'male', '1994-11-19'), ('D', 'male', '1996-03-14')]

attrgetter(attr, …) –> attrgetter object

Return a callable object that fetches the given attribute(s) from its operand. 
After f = attrgetter(‘name’), the call f(r) returns r.name. 
After g = attrgetter(‘name’, ‘date’), the call g(r) returns (r.name, r.date). 
After h = attrgetter(‘name.first’, ‘name.last’), the call h(r) returns(r.name.first, r.name.last).

個人理解就是按照物件屬性排序:

>>> 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=attrgetter('age'))  # 按物件屬性排序
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]

methodcaller(name, …) –> methodcaller object

Return a callable object that calls the given method on its operand. 
After f = methodcaller(‘name’), the call f(r) returns r.name(). 
After g = methodcaller(‘name’, ‘date’, foo=1), the call g(r) returns 
r.name(‘date’, foo=1).

methodcaller函式可以讓元素呼叫一個方法,然後按方法的返回值進行排序:

words = [‘b’, ‘a’, ‘abase’, ‘alfalfa’]
sorted(words, key=methodcaller(‘count’, ‘a’)) # word.count(‘a’)
[‘b’, ‘a’, ‘abase’, ‘alfalfa’]

sorted(words, key=lambda word: word.count(‘a’))
[‘b’, ‘a’, ‘abase’, ‘alfalfa’]
“`