深入Python中的 Collections 模塊
collections模塊是一個(gè)不用不知道,一用就上癮的模塊。這里主要介紹OrderedDict類、defaultdict類、Counter類、namedtuple類和deque類。
collections
collections的常用類型有:
- 計(jì)數(shù)器(Counter)
- 雙向隊(duì)列(deque)
- 默認(rèn)字典(defaultdict)
- 有序字典(OrderedDict)
- 可命名元組(namedtuple)
Counter
計(jì)數(shù)器(counter)以字典的形式返回序列中各個(gè)字符出現(xiàn)的次數(shù),值為key,次數(shù)為value
Counter是對(duì)字典類型的補(bǔ)充,用于追蹤值得出現(xiàn)次數(shù) 。
- import collections
- counter = collections.Counter("My name is Runsen")
- print(counter)
輸出如下
- Counter({' ': 3, 'n': 3, 'e': 2, 's': 2, 'M': 1, 'y': 1, 'a': 1, 'm': 1, 'i': 1, 'R': 1, 'u': 1})
取得元素重復(fù)次數(shù)的值
- print(counter[' '])
- 3
elements()取得計(jì)數(shù)器中的所有元素。
注:此處非所有元素集合,而是包含所有元素集合的迭代器.
- counter = collections.Counter('abcabcabcdabcdef')
- print(counter)
- # 輸出如下
- Counter({'a': 4, 'b': 4, 'c': 4, 'd': 2, 'e': 1, 'f': 1})
- print(counter.elements())
- # 輸出如下
- <itertools.chain object at 0x0000025B1477BF98>
- print(list(counter.elements()))
- # 輸出如下
- ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'e', 'f']
將Counter按照value從大到小排列,獲取前N個(gè)元素,需要使用函數(shù)most_common
- # most_common(N)數(shù)量從大到小排列,獲取前N個(gè)元素
- print(counter.most_common(3))
- # 輸出如下
- [('a', 4), ('b', 4), ('c', 4)]
sorted將Counter中的key進(jìn)行排序,返回的是所有key的列表
- # sorted()列出所有不同的元素并排序
- print(sorted(counter))
- # 輸出如下
- ['a', 'b', 'c', 'd', 'e', 'f']
將Counter轉(zhuǎn)換成字符串,字符串的join方法可以解決。注意不是原來的模樣。
- # 轉(zhuǎn)換成字符串
- print(''.join(counter.elements()))
- # aaaabbbbccccddef
- print(''.join(list(counter.elements())))
update()更新計(jì)數(shù)器,其實(shí)在原本的counter更新計(jì)數(shù)器,如果原來沒有,則新建key,如果有value則加一
- # update()更新計(jì)數(shù)器,
- d = collections.Counter('a')
- counter.update(d)
- print(counter)
- # 輸出如下
- Counter({'a': 5, 'b': 4, 'c': 4, 'd': 2, 'e': 1, 'f': 1})
update()更新計(jì)數(shù)器,那么subtract()相減計(jì)數(shù)器的values,即原來的計(jì)數(shù)器中的每一個(gè)元素的數(shù)量減去后添加的元素的數(shù)量
- counter.subtract('abdabcabcg')
- print(counter)
- # 輸出如下
- Counter({'a': 2, 'c': 2, 'b': 1, 'd': 1, 'e': 1, 'f': 1, 'g': -1})
deque
deque支持從任意一端增加和刪除元素。更為常用的兩種結(jié)構(gòu),就是棧和隊(duì)列。
deque的常見操作
- #定義一個(gè)空的雙向隊(duì)列
- d = collections.deque()
- #從右端增加元素
- d.extend("Runsen")
- d.append("Maoli")
- d.append("Python")
- d.append("king")
- #從左端增加元素
- d.appendleft('left')
- print(d)
- # 輸出如下 (注意:extend和append的區(qū)別)
- deque(['left', 'R', 'u', 'n', 's', 'e', 'n', 'Maoli', 'Python', 'king'])
- # reverse()反轉(zhuǎn)隊(duì)列
- print(d.reverse())
- d.reverse()
- print(d)
- # 輸出如下
- None
- deque(['king', 'Python', 'Maoli', 'n', 'e', 's', 'n', 'u', 'R', 'left'])
- d.reverse()
- d.extend(['qq','ww','ee'])
- print(d)
- # deque(['left', 'R', 'u', 'n', 's', 'e', 'n', 'Maoli', 'Python', 'king', 'qq', 'ww', 'ee'])
- # count()計(jì)數(shù)
- print(d.count('R'))
- # 輸出如下
- 1
- # clear()清空隊(duì)列
- d.clear()
- print(d)
- # 輸出如下
- deque([])
- # index()取得元素下標(biāo)
- print(d.index('Maoli'))
- # 輸出如下
- 7
- # insert()指定位置插入元素
- d.insert(1,'Runsen')
- print(d)
- # deque(['left', 'Runsen',R', 'u', 'n', 's', 'e', 'n', 'Maoli', 'Python', 'king', 'qq', 'ww', 'ee'])
OrderedDict
使用dict時(shí)要保持Key的順序,可以用OrderedDict。
- from collections import OrderedDict
- dic = OrderedDict()
- dic['k1'] = 'v1'
- dic['k2'] = 'v2'
- dic['k3'] = 'v3'
- print(dic)
- # 輸出如下
- OrderedDict([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')])
- # 字典所有的鍵
- print(dic.keys())
- # 輸出如下
- odict_keys(['k1', 'k2', 'k3'])
- # 字典所有值
- print(dic.values())
- # 輸出如下
- odict_values(['v1', 'v2', 'v3'])
- # items() 方法以列表返回可遍歷的(鍵, 值) 元組數(shù)組
- print(dic.items())
- # 輸出如下
- odict_items([('k1', 'v1'), ('k2', 'v2'), ('k3', 'v3')])
- #pop()方法,刪除指定的鍵值
- dic.pop('k1')
- print(dic)
- # 輸出如下
- OrderedDict([('k2', 'v2'), ('k3', 'v3')])
- #popitem()方法,默認(rèn)刪除字典最后一個(gè)元素
- dic.popitem()
- print(dic)
- # 輸出如下
- OrderedDict([('k2', 'v2')])
- # update()更新字典
- dic.update({'k1':'v1111','k10':'v10'})
- print(dic)
- # 輸出如下
- OrderedDict([('k2', 'v2'), ('k1', 'v1111'), ('k10', 'v10')])
OrderedDict和字典操作完全相同,區(qū)別在于OrderedDict的Key會(huì)按照插入的順序排列,不是Key本身排序
- >>> from collections import OrderedDict
- >>> d = dict([('a', 1), ('b', 2), ('c', 3)])
- >>> d # dict的Key是無(wú)序的
- {'a': 1, 'c': 3, 'b': 2}
- >>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
- >>> od # OrderedDict的Key是有序的
- OrderedDict([('a', 1), ('b', 2), ('c', 3)])
defaultdict
在使用字典的時(shí)候, 如果在使用不存在的key的時(shí)候發(fā)生KeyError這樣的一個(gè)報(bào)錯(cuò), 這時(shí)候就該defaultdict登場(chǎng)了。
defaultdict接受一個(gè)工廠函數(shù)作為參數(shù)來構(gòu)造:dict =defaultdict( factory_function)這個(gè)factory_function可以是list、set、str等等,作用是當(dāng)key不存在時(shí),返回的是工廠函數(shù)的默認(rèn)值,比如list對(duì)應(yīng)[ ],str對(duì)應(yīng)的是空字符串,set對(duì)應(yīng)set( ),int對(duì)應(yīng)0,如下舉例:
- from collections import defaultdict
- dict1 = defaultdict(int)
- dict2 = defaultdict(set)
- dict3 = defaultdict(str)
- dict4 = defaultdict(list)
- dict1[2] ='two'
- print(dict1[1])
- print(dict2[1])
- print(dict3[1])
- print(dict4[1])
- # 輸出如下
- 0
- set()
- []
defaultdict類接受類型名稱作為初始化函數(shù)的參數(shù),這樣使得默認(rèn)值的取值更加靈活。
- s = 'mynameisrunsen'
- d = collections.defaultdict(int)
- for k in s:
- d[k] += 1
- print(d)
- # 輸出如下
- defaultdict(<class 'int'>, {'m': 2, 'y': 1, 'n': 3, 'a': 1, 'e': 2, 'i': 1, 's': 2, 'r': 1, 'u': 1})
練習(xí)有如下值集合 [11,22,33,44,55,66,77,88,99,99]。
下面將所有大于 55的值保存至字典的第一個(gè)key中,將小于 55 的值保存至第二個(gè)key的值中。
下面通過defaultdict默認(rèn)字典對(duì)列表進(jìn)行劃分。
- all_list = [11,22,33,44,55,66,77,88,99]
- dic = collections.defaultdict(list)
- for i in all_list:
- if i > 55:
- dic['k1'].append(i)
- else:
- dic['k2'].append(i)
- print(dic)
- # 輸出如下
- defaultdict(<class 'list'>, {'k2': [11, 22, 33, 44, 55], 'k1': [66, 77, 88, 99]})
也可以使用字典,具體代碼如下。
- all_list = [11,22,33,44,55,66,77,88,99]
- dic = {}
- for i in all_list:
- if i > 55:
- if "k1" in dic.keys():
- dic['k1'].append(i)
- else:
- dic['k1'] = [i,]
- else:
- if "k2" in dic.keys():
- dic['k2'].append(i)
- else:
- dic['k2'] = [i,]
- print(dic)
- # 輸出如下
- {'k2': [11, 22, 33, 44, 55], 'k1': [66, 77, 88, 99]}
namedtuple
namedtuple是用來創(chuàng)建一個(gè)自定義的tuple對(duì)象,并且規(guī)定了tuple元素的個(gè)數(shù),并可以用屬性而不是索引來引用tuple的某個(gè)元素。
使用命名元組的步驟:
- # 將元組封裝為一個(gè)類,可以通過字段名(屬性名)來訪問元組中的值
- # 支持元組的所有操作
- from collections import namedtuple
- # 1、定義一個(gè)類
- Runsen = namedtuple('Runsen', ['name','sex','age'])
- # 2、創(chuàng)建對(duì)象
- runsen = Runsen("Runsen", "帥男", 21)
- # 3、獲取命名元組的值
- print(runsen[1]) # 支持元組的索引取值
- print(runsen[-2:]) # 支持切片
- print(runsen.name) # 支持通過字段名來取值
- # _fields,獲取命名元組的所有屬性名
- print(runsen._fields)
- # _asdict方法,將元組轉(zhuǎn)化為字典
- print(runsen._asdict())
- # 輸出如下
- 帥男
- ('帥男', 21)
- Runsen
- ('name', 'sex', 'age')
- OrderedDict([('name', 'Runsen'), ('sex', '帥男'), ('age', 21)])
本文已收錄 GitHub,傳送門~[1] ,里面更有大廠面試完整考點(diǎn),歡迎 Star。
Reference
[1]傳送門~:
https://github.com/MaoliRUNsen/runsenlearnpy100