《Python CookBook》讀書筆記-數(shù)據(jù)結(jié)構(gòu)和算法(一)

1. 把一個序列L拆分為包含n(n<=len(l))個單獨的變量

用法

data = ['ACME', 50, 90, (2017, 3, 8)]
name, shares, price, date = data
print(name, date)
name, _, _, (year, *_) = data    # 只取某幾個元素而忽略其他元素
print(name, year)
ACME (2017, 3, 8)
ACME 2017

說明

做分解操作稠肘,有時可能需要丟棄某些值梧乘,通常可以選一個一般用不到的變量名來表示這些要被丟棄的元素咕缎,如可以用 '_'企蹭,'_', 'ign(ignored)', 'ign'颁虐。對于分解未知或者任意長度的可迭代對象時忽舟,使用這種*式的語法特別有用历谍。

例子

# 計算平均分時一般要去掉最高和最低分
def drop_first_last(grades):
    first, *middle, last = grades
    return avg(middle)
# 實現(xiàn)遞歸
def sum(items):
    head, *tail = items
    return head + sum(tail) if tail else head

2. 通過heapq模塊來找最大或最小的N個元素

用法

import heapq
import random

nums = random.sample(range(-20, 50), 10) # 從range(-20, 50)中隨機取出10個元素
print(nums)
print(heapq.nlargest(3, nums))
print(heapq.nsmallest(3, nums))

dict_nums = [dict.fromkeys('a', i) for i in nums]
print(dict_nums)
print(heapq.nlargest(3, dict_nums, key=lambda s: s['a'])) # 通過接受參數(shù)key虾标,可以在更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)上進行操作
print(heapq.nsmallest(3, dict_nums, key=lambda s: s['a']))

heap = list(nums)
heapq.heapify(heap) # 把nums以堆的順序進行排列
print(heap)
print(heapq.heappop(heap)) # heap[0]總是最小那個元素寓盗,heappop取出最小的元素,取出最小元素后會重新構(gòu)造堆
print(heapq.heappop(heap))
[-1, 43, 16, 47, 31, -11, 4, 49, 13, 28]
[49, 47, 43]
[-11, -1, 4]
[{'a': -1}, {'a': 43}, {'a': 16}, {'a': 47}, {'a': 31}, {'a': -11}, {'a': 4}, {'a': 49}, {'a': 13}, {'a': 28}]
[{'a': 49}, {'a': 47}, {'a': 43}]
[{'a': -11}, {'a': -1}, {'a': 4}]
[-11, 13, -1, 43, 28, 16, 4, 49, 47, 31]
-11
-1

說明

  • 堆最重要的特性是heap[0]總是最小那個元素
  • 當(dāng)要找的元素數(shù)量相對較小時,適用nlargest()和nsmallest()贞让,注意nlargest()和nsmallest()的實際實現(xiàn)會根據(jù)適用他們的不同方式而有所不同周崭,如N僅僅集合大小時會先排序
  • 如果只是簡單的找到最小或最大的元素,則用min()和max()合適
  • 如果N和集合本身大小差不多喳张,通常更快的方法是先對集合排序续镇,然后做切片操作

3. 實現(xiàn)優(yōu)先級隊列

問題

實現(xiàn)一個隊列,它能以給定的優(yōu)先級來對元素進行排序销部,每次pop操作都會返回優(yōu)先級最高的那個元素

解決方案

import heapq

class PriorityQueue:
    def __init__(self):
        self._queue = []
        self._index = 0
        
    def push(self, item, priority):
        heapq.heappush(self._queue, (-priority, self._index, item))
        self._index += 1
        
    def pop(self):
        return heapq.heappop(self._queue)[-1]
    
pq = PriorityQueue()
pq.push('jlan', 5)
pq.push('hua', 2)
pq.push('lann', 4)
pq.push('bob', 1)
pq.push('han', 3)
print(pq._queue)
print(pq.pop())
print(pq._queue)
print(pq.pop())
[(-5, 0, 'jlan'), (-3, 4, 'han'), (-4, 2, 'lann'), (-1, 3, 'bob'), (-2, 1, 'hua')]
jlan
[(-4, 2, 'lann'), (-3, 4, 'han'), (-2, 1, 'hua'), (-1, 3, 'bob')]
lann

說明(詳解見P10)

  1. 這個方案的核心在于heapq模塊的使用摸航。heappush()和heappop()分別從_queue中插入和移除,且保證列表中第一個元素的優(yōu)先級最低舅桩。heappop()總是返回‘最小’元素酱虎,因此這是隊列能彈出正確元素的關(guān)鍵。
  2. 在這段代碼中擂涛,隊列以元組(-priority, index, item)的形式組成读串,priority取負值是為了讓隊列能夠按優(yōu)先級從高到底排序(正常情況下,堆是按從小到大排序的),構(gòu)造堆時按-priority排序撒妈,當(dāng)priority相同時按index排序恢暖。
  3. 變量index的作用是為了將具有相同優(yōu)先級的元素以適當(dāng)?shù)捻樞蚺帕校ㄒ匀腙犿樞颍?/li>

字典操作

  • 將鍵映射到多個值上
from collections import defaultdict

d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
print(d)
defaultdict(<class 'list'>, {'a': [1, 2]})
  • 有序字典
    使用collections.OrderedDict可以保持字典有序,OrderedDict內(nèi)部維護了一個雙向鏈表狰右,會根據(jù)元素加入的順序來排列鍵的位置杰捂。OrderedDict的大小是普通字典的2倍多。

  • 在字典上進行求最大值棋蚌,最小值等操作

prices = {
    'apple': 2,
    'banada': 3,
    'orange': 1,
    'peach': 4
}

# 在字典上執(zhí)行常見的操作嫁佳,只會處理鍵,而不是值
min(prices) # 返回'apple'
max(prices) # 返回'peach'

# 可以用dict.values()來處理值
min(prices.values()) # 返回 1
max(prices.values()) # 返回 4

min(prices, key=lambda x: prices[x]) # 返回'orange'
max(prices, key=lambda x: prices[x]) # 返回'peach'

# 對字典進行求最大值谷暮,最小值等操作一般用下邊的方法
min(zip(prices.values(), prices.keys())) # 返回(1, 'orange')
max(zip(prices.values(), prices.keys())) # 返回(4, 'orange')
# zip()創(chuàng)建了一個迭代器蒿往,其內(nèi)容只能被消費一次
# 涉及(value, key)對的比較時,如果多個條目有相同的value坷备,此時將根據(jù)key進行判定
(4, 'peach')
  • 在字典中尋找相同點
# 找出兩個字典可能相同的地方(相同的鍵或者值)
a = {'x': 1, 'y': 2, 'z': 3}
b = {'w': 11, 'y': 2, 'z': 13}

# a和b相同的鍵
a.keys() & b.keys() # 返回 {'y', 'z'}

# 在a中但是不在b中的鍵
a.keys() - b.keys() # 返回 {'x'}

# a和b中相同的{key: value}
a.items() & b.items() # 返回 {('y', 2)}
{('y', 2)}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末熄浓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子省撑,更是在濱河造成了極大的恐慌赌蔑,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件竟秫,死亡現(xiàn)場離奇詭異娃惯,居然都是意外死亡,警方通過查閱死者的電腦和手機肥败,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門趾浅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愕提,“玉大人,你說我怎么就攤上這事皿哨∏城龋” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵证膨,是天一觀的道長如输。 經(jīng)常有香客問我,道長央勒,這世上最難降的妖魔是什么不见? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮崔步,結(jié)果婚禮上稳吮,老公的妹妹穿的比我還像新娘。我一直安慰自己井濒,他們只是感情好灶似,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著眼虱,像睡著了一般喻奥。 火紅的嫁衣襯著肌膚如雪席纽。 梳的紋絲不亂的頭發(fā)上捏悬,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音润梯,去河邊找鬼过牙。 笑死,一個胖子當(dāng)著我的面吹牛纺铭,可吹牛的內(nèi)容都是我干的寇钉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼舶赔,長吁一口氣:“原來是場噩夢啊……” “哼扫倡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起竟纳,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤撵溃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后锥累,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缘挑,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年桶略,在試婚紗的時候發(fā)現(xiàn)自己被綠了语淘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诲宇。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖惶翻,靈堂內(nèi)的尸體忽然破棺而出姑蓝,到底是詐尸還是另有隱情,我是刑警寧澤吕粗,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布它掂,位于F島的核電站,受9級特大地震影響溯泣,放射性物質(zhì)發(fā)生泄漏虐秋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一垃沦、第九天 我趴在偏房一處隱蔽的房頂上張望客给。 院中可真熱鬧,春花似錦肢簿、人聲如沸靶剑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桩引。三九已至,卻和暖如春收夸,著一層夾襖步出監(jiān)牢的瞬間坑匠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工卧惜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留厘灼,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓咽瓷,卻偏偏與公主長得像设凹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子茅姜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容