每日一課 | Python 進(jìn)階編程之字典的高級(jí)用法

一、 collections 中 defaultdict 的使用

1.1 字典的鍵映射多個(gè)值

將下面的列表轉(zhuǎn)成字典

l = [('a',2),('b',3),('a',1),('b',4),('a',3),('a',1),('b',3)]

一個(gè)字典就是一個(gè)鍵對(duì)應(yīng)一個(gè)單值的映射,而上面的列表中有相同鍵。如果你想要一個(gè)鍵映射多個(gè)值,那么就需要將這多個(gè)值放到另外的序列中,比如 list 或者 set 里面,像下面這樣:

d = {
'a': [1, 2, 3],
'b': [4, 5]
}
e = {
'a': {1, 2, 3},
'b': {4, 5}
}

你可以很方便的使用 collections 模塊中的 defaultdict 來(lái)構(gòu)造這樣的字典。defaultdict 的一個(gè)特征是它會(huì)自動(dòng)初始化每個(gè) key 剛開(kāi)始對(duì)應(yīng)的值。

from collections import defaultdict

l = [('a', 2), ('b', 3), ('a', 1), ('b', 4), ('a', 3), ('a', 1), ('b', 3)]

#集合方式
d = defaultdict(set)
for key, value in l:
    d[key].add(value)

#列表方式
d = defaultdict(list)
for key, value in l:
    d[key].append(value)
print(d)

print(defaultdict(list, {'a': [2, 1, 3, 1], 'b': [3, 4, 3]}))

當(dāng)然這個(gè)默認(rèn)的容器不一定是 list, 也可以是集合 set。根據(jù)自己的需求選擇用 list 還是 set 。如果你想保持元素的插入順序就應(yīng)該使用列表,如果想去掉重復(fù)元素就使用集合!

1.2 統(tǒng)計(jì)字典中某個(gè)值出現(xiàn)的次數(shù)

來(lái)源于微信交流群里一個(gè)朋友工作中的問(wèn)題,列表中有很多字典,需要統(tǒng)計(jì)字典中相同的鍵對(duì)應(yīng)的值的和


image.png

利用 defaultdict 設(shè)置默認(rèn)值的方法 defaultdict(int),代碼如下:

objs = [{'F29958SVDK6': 12}, {'F29958SVDK5': 12}, {'F29958SVDK6': 12}, {'F29958SVDK6': 12}, {'F29958SVDK6': 12}]
for obj in objs:
    for key, value in obj.items():
        d[key] += value
print(d)

print(defaultdict(int, {'F29958SVDK6': 60}))

二、collections 創(chuàng)建有序字典

字典dict是無(wú)序的,如果我們想要有序的dict,可以使用OrdereDict 。示例如下

from collections import OrderedDict

d = OrderedDict()

d['bar'] = 2
d['non'] = 8
d['sek'] = 5

print(d)
print(OrderedDict([('bar', 2), ('non', 8), ('sek', 5)]))

OrderedDict 內(nèi)部維護(hù)著一個(gè)根據(jù)鍵插入順序排序的雙向鏈表。每次當(dāng)一個(gè)新的元 素插入進(jìn)來(lái)的時(shí)候,它會(huì)被放到鏈表的尾部。對(duì)于一個(gè)已經(jīng)存在的鍵的重復(fù)賦值不會(huì) 改變鍵的順序。

需要注意的是,一個(gè) OrderedDict 的大小是一個(gè)普通字典的兩倍,因?yàn)樗鼉?nèi)部維 護(hù)著另外一個(gè)鏈表。所以如果你要構(gòu)建一個(gè)需要大量 OrderedDict 實(shí)例的數(shù)據(jù)結(jié)構(gòu)的 時(shí)候 (比如讀取 100,000 行 CSV 數(shù)據(jù)到一個(gè) OrderedDict 列表中去).

那么你就得仔細(xì)權(quán)衡一下是否使用 OrderedDict 帶來(lái)的好處要大過(guò)額外內(nèi)存消耗的影響。

2.1 改變 key-value 的順序

OrderedDict 是有序的字典,同時(shí)也能改變其順序。比如我們想要改變有序的 OrderedDict 對(duì)象的 key-value 順序,可以使用 move_to_end(key)。還是以上面創(chuàng)建的有序字典為例子

from collections import OrderedDict

d = OrderedDict()

d['bar'] = 2
d['non'] = 8
d['sek'] = 5
d.move_to_end("bar",last=False)
print(d)
print(OrderedDict([('bar', 2), ('non', 8), ('sek', 5)]))

可以看到之前排在第一位的 bar被移到最后一位了。move_to_end 還接收一個(gè)關(guān)鍵字參數(shù) last。last 默認(rèn)為 True,當(dāng) last = False 的時(shí)候,表示將該鍵移動(dòng)到最前面!

2.2 刪除 key_value

如果我們要?jiǎng)h除有序字典中的 key-value, 可以使用 popitem 方法, popitem(last=True) 按照先進(jìn)后出的順序刪除 dict中 的 key-value,popitem(last=False) 按照先進(jìn)先出的規(guī)則刪除 dict 中的 key-value。

print(OrderedDict([('bar', 2), ('non', 8), ('sek', 5)]))
d.popitem(last=False)
print(d)

三、字典排序

利用Python 內(nèi)置函數(shù) sorted 對(duì)字典的鍵或者值進(jìn)行排序,首先來(lái)了解下 sorted 函數(shù)

sorted(iterable, key=None, reverse=False)

參數(shù)說(shuō)明:
iterable -- 可迭代對(duì)象
key -- 主要是用來(lái)進(jìn)行比較的元素,只有一個(gè)參數(shù),具體的函數(shù)的參數(shù)就是取自于可迭代對(duì)象中,指定可迭代對(duì)象中的一個(gè)元素來(lái)進(jìn)行排序。
reverse -- 排序規(guī)則,reverse = True 降序 , reverse = False 升序(默認(rèn))。

3.1 按照 key 進(jìn)行排序

理解了 sorted 函數(shù)就好辦了,代碼如下:

d = {'b':3,'a':4,'c':2,'d':1}
print(d.items())
print(sorted(d.items(), key=lambda i:i[0],reverse=True))
3.2 按照 value 進(jìn)行排序
sorted(d.items(), key=lambda i:i[1])

結(jié)果:

[('d', 1), ('c', 2), ('b', 3), ('a', 4)]

注意排序后的返回值是一個(gè)list,而原字典中的名值對(duì)被轉(zhuǎn)換為了list中的元組。

四、通過(guò)某個(gè)關(guān)鍵字排序一個(gè)字典列表

假設(shè)你有一個(gè)字典列表, 如下:

rows = [ {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
 {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
 {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}, 
{'fname': 'Big', 'lname': 'Jones', 'uid': 1004} ] 

你想根據(jù)某個(gè)或某幾個(gè)字典字段來(lái)排序這個(gè)列表。

通過(guò)使用 operator 模塊的 itemgetter 函數(shù),可以非常容易的排序這樣的數(shù)據(jù)結(jié)構(gòu),代碼如下:

from operator import itemgetter

rows_by_fname = sorted(rows, key=itemgetter('fname'))
print( rows_by_fname)

結(jié)果:

[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004},
 {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
 {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
 {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]
rows_by_uid = sorted(rows, key=itemgetter('uid'))
print( rows_by_uid)

結(jié)果:

[{'fname': 'John', 'lname': 'Cleese', 'uid': 1001},
 {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
 {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
 {'fname': 'Big', 'lname': 'Jones', 'uid': 1004}]

itemgetter() 函數(shù)也支持多個(gè) keys,比如下面的代碼:

rows_by_lfname = sorted(rows, key=itemgetter('lname','fname'))
print( rows_by_fname)

結(jié)果:

[{'fname': 'Big', 'lname': 'Jones', 'uid': 1004},
 {'fname': 'Brian', 'lname': 'Jones', 'uid': 1003},
 {'fname': 'David', 'lname': 'Beazley', 'uid': 1002},
 {'fname': 'John', 'lname': 'Cleese', 'uid': 1001}]

好了,上面就是字典的一些高級(jí)用法。
希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,每天進(jìn)步一點(diǎn)點(diǎn),加油

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容