python之排序操作及heapq模組

二十一發表於2019-02-16

說到排序,很多人可能第一想到的就是sorted,但是你可能不知道python中其實還有還就中方法喲,並且好多種場景下效率都會比sorted高。那麼接下來我就依次來介紹我所知道的排序操作。
sorted(iterable, *, key=None, reverse=False)

list1=[1,6,4,3,9,5]
list2=[`12`,`a6`,`4`,`c34`,`b9`,`5`]

print(sorted(list1))    #[1, 3, 4, 5, 6, 9]
print(sorted(list2))    #[`12`, `4`, `5`, `a6`, `b9`, `c34`]
#總結上面兩種排序:字串排序根據元素首字元的ASCII比較進行排序,
#數字型別按照大小排序,數字不能混合排序

list3=[
    {`name`:`jim`,`age`:23,`price`:500},
    {`name`:`mase`,`age`:23,`price`:600},
    {`name`:`tom`,`age`:25,`price`:2000},
    {`name`:`alice`,`age`:22,`price`:300},
    {`name`:`rose`,`age`:21,`price`:2400},
]

print(sorted(list3,key=lambda s:(s[`age`],s[`price`])))
#[{`name`: `rose`, `age`: 21, `price`: 2400}, {`name`: `alice`, `age`: 22, `price`: 300}, {`name`: `jim`, `age`: 23, `price`: 500}, {`name`: `mase`, `age`: 23, `price`: 600}, {`name`: `tom`, `age`: 25, `price`: 2000}]

最後的reverse引數我就不作說明了,就是把結果進行倒序,可用作降序排列
介紹一種比lambda效率高的方式:
operator模組中的方法itemgetter
>>> itemgetter(1)(`ABCDEFG`)
`B`
>>> itemgetter(1,3,5)(`ABCDEFG`)
(`B`, `D`, `F`)
>>> itemgetter(slice(2,None))(`ABCDEFG`)
`CDEFG
運用到上述程式碼
print(sorted(list3,key=itemgetter(`age`,`price`)))    #結果同上但效率會比較高

接下來的排序操作涉及到一個非常重要的一種資料結構——堆,不過今天我主要介紹這個模組中的方法,具體什麼是堆,及其還有一種資料結構——棧,有時間我會專門寫一篇文章來介紹。
heapq(Python內建的模組)

__all__ = [`heappush`, `heappop`, `heapify`, `heapreplace`, `merge`,
           `nlargest`, `nsmallest`, `heappushpop`]

接下來我們一一介紹。
nlargest與nsmallest,通過字面意思可以看出方法大致的作用,接下來動手測驗

nlargest(n, iterable, key=None)
nsmallest(n, iterable, key=None)
#n:查詢個數    iterable:可迭代物件    key:同sorted

list1=[1,6,4,3,9,5]
list2=[`12`,`a6`,`4`,`c34`,`b9`,`5`]
list3=[
    {`name`:`jim`,`age`:23,`price`:500},
    {`name`:`mase`,`age`:23,`price`:600},
    {`name`:`tom`,`age`:25,`price`:2000},
    {`name`:`alice`,`age`:22,`price`:300},
    {`name`:`rose`,`age`:21,`price`:2400},
]

from operator import itemgetter
import heapq

print(heapq.nlargest(len(list1),list1))
print(heapq.nlargest(len(list2),list2))
print(heapq.nlargest(len(list3),list3,key=itemgetter(`age`,`price`)))
#以上程式碼輸出結果同sorted

print(heapq.nsmallest(len(list1),list1))
print(heapq.nsmallest(len(list2),list2))
print(heapq.nsmallest(len(list3),list3,key=itemgetter(`age`,`price`)))
#結果是降序
[1, 3, 4, 5, 6, 9]
[`12`, `4`, `5`, `a6`, `b9`, `c34`]
[{`name`: `rose`, `age`: 21, `price`: 2400}, {`name`: `alice`, `age`: 22, `price`: 300}, {`name`: `jim`, `age`: 23, `price`: 500}, {`name`: `mase`, `age`: 23, `price`: 600}, {`name`: `tom`, `age`: 25, `price`: 2000}]

heappush,heappop,heapify,heapreplace,heappushpop
堆結構特點:heap[0]永遠是最小的元素(利用此特性排序)

heapify:對序列進行堆排序,
heappush:在堆序列中新增值
heappop:刪除最小值並返回
heappushpop:新增並刪除堆中最小值且返回,新增之後刪除
heapreplace:新增並刪除隊中最小值且返回,刪除之後新增

nums=[54,23,64.,323,53,3,212,453,65]
heapify(nums)    #先進行堆排序
print(heappop(nums))    #3
print(heappush(nums,50))    #新增操作,返回None
print(heappushpop(nums,10))    #由於是新增後刪除,所以返回10
print(heappop(nums))    #23
print(heapreplace(nums,10))    #和heappushpop,返回50
print(nums)    #[10, 53, 54, 65, 323, 64.0, 212, 453]

merge:合併多個序列

list1 = [1, 2, 3, 4, 5, 12]
set1 = {2, 3, 9, 23, 54}
s = list(merge(list1,set1))
print(s)    #[1, 2, 2, 3, 3, 4, 5, 9, 12, 54, 23]
#發現輸出結果不僅進行了合併,還進行了排序,有意思哈,可是換個程式碼測驗,你再看一下

list1 = [31, 2, 83, 24, 5, 12]
set1 = {2, 83, 9, 23, 54}
s = list(merge(list1,set1))
print(s)    #[2, 9, 31, 2, 83, 24, 5, 12, 83, 54, 23]
#你們肯定想這是什麼鬼,一點都沒有頭緒,其實經過我的多次測驗,還是有規律的,但是由於沒有什麼作用就不大篇幅說明了,喜歡刨根問題的小夥伴可以嘗試自己思考一下。

小夥伴們有沒有想我為何介紹這個模組,並且和排序放在一起呢,其實在很多時候我們需要找序列中的前幾個最大值或者最小值,使用此模組中的方法是最好不過的了。
如果需要全部排序我們使用sorted,需要查詢最大或最小的幾個或者多個我們使用alargest/asmallest,查詢最大最小使用max/min

相關文章