關於Python的多重排序


Python預置的list.sort()、sorted()方法可實現各種數組的排序,但支持的只限於一個key,如果要多重排序,目前所知的方法只有自定義了。

Help on built-in function sorted in module __builtin__:

sorted(...)

    sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list

查看sorted的幫助可知,cmp參數在第二個位置,不過一般都以kwargs的形式顯式寫出。

 

關於cmp,cmp定義的函數接收源數組中相鄰的兩個元素,在比較大小后分別返回負值、0或正值,分別代表第一個值小於、等於或大於第二個值,然后再按照key和reverse的設定去進行排序。

>>> a=list(range(10))
>>> a.reverse()    # reverse為on place方法
>>> a
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> a.sort(cmp=lambda a,b: a-b)    # a-b < 0  默認reverse為False,升順排序,結果為正常順序
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a.sort(cmp=lambda a,b: b-a)    # b-a > 0  lambda返回正值,認為a > b,按照“升順”排序,實際結果為降序
>>> a                              # sort同樣是on place方法
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> 

對於多重排序,可利用cmp方法,分別定義key的優先級,以及排序方式,達到多重、獨立順序的排序方式實現。

代碼如下:

d1 = {1:23, 'b': 62}
d2 = {1:24, 'b': 2}
d3 = {1:23, 'b': 54}
d4 = {1:23, 'b': 1}
d5 = {1:01, 'b': 9}
d6 = {1:23, 'b': 32}
d7 = {1:05, 'b': 33}
d8 = {1:39, 'b': 100}

li = [d1, d2, d3, d4, d5, d6, d7, d8]

def cmpf(a, b, key1, key2):
     if (a[key1] != b[key1]):
             return a[key1] - b[key1]
     else:
             return a[key2] - b[key2]

def rcmpf(a, b, key1, key2):
     if (a[key1] != b[key1]):
             return b[key1] - a[key1]
     else:
             return a[key2] - b[key2]

# key1、key2均為升序
sorted(li, cmp=lambda a,b: cmpf(a, b, 1, 'b'))

# key1降序、key2升序
sorted(li, cmp=lambda a,b: rcmpf(a, b, 1, 'b'))

執行結果如下:

>>> sorted(li, cmp=lambda a,b: cmpf(a, b, 1, 'b'))
[{1: 1, 'b': 9}, {1: 5, 'b': 33}, {1: 23, 'b': 1}, {1: 23, 'b': 32}, {1: 23, 'b': 54}, {1: 23, 'b': 62}, {1: 24, 'b': 2}, {1: 39, 'b': 100}]
>>> 
>>> sorted(li, cmp=lambda a,b: rcmpf(a, b, 1, 'b'))
[{1: 39, 'b': 100}, {1: 24, 'b': 2}, {1: 23, 'b': 1}, {1: 23, 'b': 32}, {1: 23, 'b': 54}, {1: 23, 'b': 62}, {1: 5, 'b': 33}, {1: 1, 'b': 9}]
>>> 

可以看到混合排序結果正常。

 

PS:按照預想,這種方式應該適用於所有可以指定多個key的數據結構,不過仍待驗證。

 

對於Python3,sort方法取消了cmp參數,官方給出的解決方案是進行多次排序,優先級低的字段先排序,然后逐個根據優先級高的字段排序

>>> d1 = {1:23, 'b': 62}
>>> d2 = {1:24, 'b': 2}
>>> d3 = {1:23, 'b': 54}
>>> d4 = {1:23, 'b': 1}
>>> d5 = {1:1, 'b': 9}
>>> d6 = {1:23, 'b': 32}
>>> d7 = {1:5, 'b': 33}
>>> d8 = {1:39, 'b': 100}
>>> li = [d1, d2, d3, d4, d5, d6, d7, d8]
>>> li.sort(key=lambda e: e['b'])  # 現根據'b'進行排序,優先級較低
>>> pprint(li)
[{1: 23, 'b': 1},
 {1: 24, 'b': 2},
 {1: 1, 'b': 9},
 {1: 23, 'b': 32},
 {1: 5, 'b': 33},
 {1: 23, 'b': 54},
 {1: 23, 'b': 62},
 {1: 39, 'b': 100}]
>>> li.sort(key=lambda e: e[1])  # 再根據1進行排序,優先級高於'b'
>>> pprint(li)
[{1: 1, 'b': 9},
 {1: 5, 'b': 33},
 {1: 23, 'b': 1},
 {1: 23, 'b': 32},
 {1: 23, 'b': 54},
 {1: 23, 'b': 62},
 {1: 24, 'b': 2},
 {1: 39, 'b': 100}]
>>> 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM