1. 程式人生 > 其它 >Python入門之collections模組

Python入門之collections模組

技術標籤:Educoder實訓之Python

第1關:命名元組 (namedtuple)
任務描述
本關任務:完成對命名元組的簡單操作。
命名元組 (namedtuple)
Python 中提供了基礎的不可變資料結構元組tuple,對元組元素的訪問需通過索引來完成,對此需要熟記每個下標對應的具體含義。如果元素數量一多,要記清楚這些東西就會比較麻煩了,於是就出現了命名元組namedtuple。
建立命名元組
命名元組的建構函式接受兩個引數typename,field_names:
typename:元組的名字;
field_names:元組各個元素的名稱,也就是屬性名稱。
比如:
collections.namedtuple(“Point”,[“x”,“y”])

這樣就建立了一個叫做Point的命名元組類,它擁有兩個屬性x,y。
第二個引數[“x”,“y”]也可以寫成"x y"或者"x,y",即用空格或者逗號隔開屬性名,即:
collections.namedtuple(“Point”,“x y”)
collections.namedtuple(“Point”,“x,y”)
我們可以將其賦值給一個變數:
Point = collections.namedtuple(“Point”,“x,y”)
p = collections.namedtuple(“Point”,“x,y”) #變數名不一定要和第一個引數相同
以上得到的變數Point或者p並不直接是一個元組物件,它只是一個類,如果要建立它的例項,則需要像建立類例項一樣呼叫它:
p1 = Point(x = 0, y = 0)
p2 = p(x = 1, y = 1)
這樣就建立了兩個例項p1,p2,他們的內容分別是x = 0,y = 0,x = 1,y = 1。
訪問命名元組的元素
通過collections.namedtuple建立的命名元組類,實際上是元組類的子類,因此命名元組也可以通過索引訪問元素:
print(p1[0])
print(p1[1])
得到的結果:
0
0
當然,命名元組也可以通過屬性訪問:
print(p2.x)
print(p2.y)
得到的結果:
1
1
修改元素
如果需要修改元組的元素,則不能簡單的使用p1.x = 1,需要呼叫成員函式_replace(),它會返回一個包含新值的新例項,比如:
p1 = p1._replace(x = 1) #將p1的x值從0換到1
程式設計要求
根據右邊編輯器中各個函式中的提示,將函式Begin-End區間程式碼補充完整,使得程式能夠正常執行並輸出正確的結果。編輯區的3個函式,將按照如下順序被呼叫:
p = CreatePoint()
PrintPoint§
p = IncX§
PrintPoint§
p = IncY§
PrintPoint§
提示:後兩個函式需要用到函式_replace()。
####測試說明
正確的補充程式碼後,應該得到的結果:
當前位置:x = 0,y = 0
當前位置:x = 1,y = 0
當前位置:x = 1,y = 1
開始你的任務吧,祝你成功!
參考答案:

import collections
def CreatePoint():
    # ********** Begin ********** #
    Point = collections.namedtuple("Point","x,y")
    p = Point(x = 0, y = 0)
    return p
    # ********** End ********** #
def IncX(p):
    # ********** Begin ********** #
    p = p._replace(x = 1)
    return p
    # ********** End ********** #
def IncY(p):
    # ********** Begin ********** #
    p = p._replace(y = 1)
    return p
    # ********** End ********** #
def PrintPoint(p):
    print("當前位置:x = %d,y = %d" % p)

第2關:計數器 (Counter)
任務描述
本關任務:編寫一個對輸入的字串,進行計數的程式。
計數器(Counter)
計數器是一個無序容器,用於記錄各種值出現的次數。它採用鍵值對的形式儲存,要記錄的值作為key,這個值出現的次數作為value,value值可正可負。
#####建立計數器
要建立一個計數器例項,可以呼叫它的無參建構函式:
c = collections.Counter()
這樣就建立了一個空的計數器例項c。
也可以從list,tuple,dict,字串等**可迭代物件(iterable)**建立:
c = collections.Counter([‘a’,‘a’,‘b’,‘b’,‘c’]) #從list建立
c = collections.Counter((‘a’,‘a’,‘b’,‘b’,‘c’)) #從tuple建立
c = collections.Counter({‘a’:2,‘b’:2,‘c’:1}) #從dict建立
c = collections.Counter(“aabbc”) #從字串建立
上面四條語句創建出來的計數器c都是相同的:
{‘a’: 2, ‘b’: 2, ‘c’: 1}
最後,你也可以直接指定鍵值對,來建立計數器:
c = collections.Counter(a=2,b=2,c=1)
創建出來的計數器c,與上面四條語句建立的計數器c是相同的。
#####訪問元素
計數器是dict的子類,因此可以像使用dict那樣訪問計數器元素:
print(c[‘a’])
print(c[‘b’])
print(c.c)
得到的結果是:
2
2
1
不過與dict不同的是,當訪問計數器中不存在的元素的時候,不會產生異常,而是返回0,比如:
print(c[‘d’]) #c中沒有d元素,但不會發生異常
上面的程式碼能夠正常執行,並且結果是:0
增加計數與減少計數
要改變計數器中某一元素的值,除了可以使用操作dict的方式:c.a = XXX外,計數器還提供了兩個成員函式update和subt\fract。
update函式接受一個可迭代物件,然後將這個物件中各種值出現的次數加到計數器中,比如:
c.update(“aabbcd”) #字串也是可迭代物件
上面這行語句執行後,c的值從原來的:
{‘a’: 2, ‘b’: 2, ‘c’: 1}
增加到了:
{‘a’: 4, ‘b’: 4, ‘c’: 2, ‘d’: 1}
subtract函式與update函式類似,不過它是從計數器中減去可迭代物件中各種值出現的次數,比如:
c.subtract(“aabbcd”)
上面這行語句執行後,c的值從原來的:
{‘a’: 4, ‘b’: 4, ‘c’: 2, ‘d’: 1}
減少到了:
{‘a’: 2, ‘b’: 2, ‘c’: 1, ‘d’: 0}
刪除元素
從上面的例子可以發現,當計數器中一個元素的值減少到0時,它並不會自動從計數器中刪除,如果要刪除元素,可以使用del函式:
del(c[‘d’])
上面這行語句執行後,c的值從原來的:
{‘a’: 2, ‘b’: 2, ‘c’: 1, ‘d’: 0}
變成了:
{‘a’: 2, ‘b’: 2, ‘c’: 1}
即元素d被刪除了。
TopN操作
計數器還提供了一個獲取出現次數最多的n個元素的成員函式most_common,它返回包含這些元素的list,比如:
top1 = c.most_common(1) #出現次數最多的元素
print(top1)
top2 = c.most_common(2) #出現次數最多的兩個元素
print(top2)
all = c.most_common() #不提供引數則返回所有元素
print(all)
得到的結果是:
[(‘a’, 2)]
[(‘a’, 2), (‘b’, 2)]
[(‘a’, 2), (‘b’, 2), (‘c’, 1)]
注意:如果有多個元素的值相同,那麼它們之間的順序是不可確定的,不要在它們的順序上作任何假設。
程式設計要求
根據提示,在右側編輯器Begin-End區間補充程式碼,完成函式功能,函式需要讀取6行輸入,然後進行如下操作:
將偶數行的資料加到計數器中;
將奇數行的資料從計數器中減去。
注意:行數是從0開始的,最後輸出計數器中的所有元素。
測試說明
平臺會對你編寫的程式碼進行測試:
測試輸入:
aabbc
aabbc
aabbc
aabbc
aabbc
aabbc
預期輸出:
[(‘a’, 0), (‘b’, 0), (‘c’, 0)]
測試輸入:
a
b
a
b
a
b
預期輸出:
[(‘a’, 3), (‘b’, -3)]
開始你的任務吧,祝你成功!
參考程式碼:

import collections
def Func():
    c = collections.Counter()
    for i in range(1,7):
        data = input()
        # ********** Begin ********** #
        if(i%2!=0):
            c.update(data)
        else :
            c.subtract(data)
        # ********** End ********** #
    print(c.most_common())

第3關:雙向佇列 (deque)
任務描述
本關任務:編寫一個能輸出“震盪”佇列的程式。
雙向佇列 (deque)
雙向佇列是一種能在佇列兩端都進行入隊、出隊操作的資料結構,比普通的佇列更加靈活也更加複雜。
建立雙向佇列
就像計數器Counter,雙向佇列可以呼叫無參建構函式建立一個空佇列,也可以使用可迭代物件建立,並初始化一個佇列,比如:
d = collections.deque() #建立一個空佇列
d = collections.deque([‘a’,‘b’,‘c’]) #從list建立
d = collections.deque((‘a’,‘b’,‘c’)) #從tuple建立
d = collections.deque({‘a’:0,‘b’:1,‘c’:2}) #從dict建立
d = collections.deque(“abc”) #從字串建立
第一行語句建立一個空佇列,下面四行語句建立了含有元素a,b,c的佇列,要注意當從dict建立時,使用的是它的鍵key,而不是值value。
佇列操作
雙向佇列與list類似,也有append和pop這兩個成員函式,他們的作用分別是向佇列的右邊增加元素和從佇列的右邊刪除並返回一個元素,比如:
d.append(‘d’) #向右邊增加一個元素’d’
print(d)
d.pop() #從右邊刪除一個元素
print(d)
得到的結果:
deque([‘a’, ‘b’, ‘c’, ‘d’])
deque([‘a’, ‘b’, ‘c’])
與append,pop相對應的,還有一組對佇列左邊進行操作的函式:appendleft,popleft,用法也與前面的一組類似:
d.appendleft(’+’) #向左邊增加一個元素’+’
print(d)
d.popleft() #從左邊刪除一個元素
print(d)
得到的結果:
deque([’+’, ‘a’, ‘b’, ‘c’])
deque([‘a’, ‘b’, ‘c’])
雙向佇列還提供了一對操作:extend和extendleft,用於將一個可迭代物件的所有迭代值,依次加入到佇列的右邊或者左邊:
d1 = collections.deque()
d1.extend(“123”)
print(d1)
d1 = collections.deque()
d1.extendleft(“123”)
print(d1)
得到的結果是:
deque([‘1’, ‘2’, ‘3’])
deque([‘3’, ‘2’, ‘1’])
可以注意到,上下兩個結果的值的順序是相反的。
程式設計要求
根據提示,補充右側編輯器Begin-End區間程式碼,完成函式功能,函式讀取輸入的一個數字n(n≥0),然後輸出一個有n個元素,元素從0到n-1的“震盪”的佇列,“震盪”的定義見測試說明。
測試說明
當輸入:3時,輸出的“震盪”佇列應該是:
deque([1, 0, 2])
當輸入:5時,輸出的“震盪”佇列應該是:
deque([3, 1, 0, 2, 4])
怎麼樣,看出其中的規律了嗎?
開始你的任務吧,祝你成功!
參考程式碼:

import collections
def Func():
    d = collections.deque()
    n = int(input())
    # ********** Begin ********** #
    if(n>=0):
        d=collections.deque()
        for i in range (n):
            if(i%2!=0):
                d.appendleft(i)
            else:
                d.append(i)
    # ********** End ********** #
    print(d)

第4關:有序字典 (OrderedDict)
任務描述
本關任務:讀取資料建立n個鍵值對,將其排序後放入有序字典並輸出。
有序字典 (OrderedDict)
有序字典和普通的dict基本上是相似的,只有一點不同,那就是有序字典中鍵值對的順序會保留插入時的順序。
建立有序字典
有序字典的建立方法和普通的dict類似,不過由於多了保留順序的功能,因此在使用可迭代物件建立有序字典時,可以對它先排個序,讓創建出來的字典元素也是有序的:
data = [(‘a’,1),(‘b’,3),(‘c’,2)]
od = collections.OrderedDict(sorted(data,key=lambda s:s[0]))#按資料中key值的大小排序
print(od)
od = collections.OrderedDict(sorted(data,key=lambda s:s[1]))#按資料中value值的大小排序
print(od)
得到的結果:
OrderedDict([(‘a’, 1), (‘b’, 3), (‘c’, 2)])
OrderedDict([(‘a’, 1), (‘c’, 2), (‘b’, 3)])
這裡使用的sorted函式,它返回對一個可迭代物件排序後的結果,如果可迭代物件的元素不能直接進行比較(比如元素是一個list或tuple等),則需要指定key函式。
這裡使用lambda表示式lambda s:s[0]和lambda s:s[1],分別指定key為data中每個元素(tuple型別)的第一個元素和第二個元素。
修改順序
有序字典提供了一個move_to_end函式,這個函式可以將指定的鍵值對移動到最前面或者最後面,即最左邊或最右邊:
dt = collections.OrderedDict()
dt[‘a’] = 0
dt[‘b’] = 1
dt[‘c’] = 2
dt.move_to_end(‘b’,last = False) #將b鍵值對移動到最前方
print(dt)
dt.move_to_end(‘b’,last = True) #將b鍵值對移動到最後方
print(dt)
得到的結果:
OrderedDict([(‘b’, 1), (‘a’, 0), (‘c’, 2)])
OrderedDict([(‘a’, 0), (‘c’, 2), (‘b’, 1)])
程式設計要求
根據提示,在右側編輯器Begin-End區間補充程式碼,實現函式功能:讀取n(n>0)行輸入,以每一行的資料為key,行號(從0開始)為value,建立n對鍵值對,然後將他們按照key排序後,放入一個有序字典,最後輸出這個有序字典。
測試說明
平臺會對你編寫的程式碼進行測試:
測試輸入:
3
a
c
b
預期輸出:
OrderedDict([(‘a’, 0), (‘b’, 2), (‘c’, 1)])
測試輸入:
4
A
B
D
C
預期輸出:
OrderedDict([(‘A’, 0), (‘B’, 1), (‘C’, 3), (‘D’, 2)])
開始你的任務吧,祝你成功!
參考程式碼:

import collections
def Func():
    od = collections.OrderedDict()
    n = int(input())
    for i in range(n):
        key = input()
        od[key]=i
        od=collections.OrderedDict(sorted(od.items(),key=lambda item:item[0]))
    print(od)

第5關:預設字典 (defaultdict)
任務描述
本關任務:建立不同型別的預設字典。
預設字典 (defaultdict)
預設字典的功能與dict基本相同,但在訪問一個不存在的key時,預設字典會提供一個預設值,而不是引發異常。
#####建立預設字典
預設字典的建構函式接受一個工廠函式default_factory作為引數,可以將一個型別名看做是一個工廠函式,比如list,tuple,str等。
這個函式會在要生成預設值的時候無參呼叫,如果使用型別名作為工廠函式,則這個型別必須要有無參建構函式,比如:
dd = collections.defaultdict(int) #使用int作為工廠函式
print(dd[‘a’]) #訪問不存在的key:‘a’
dd = collections.defaultdict(tuple) #使用tuple作為工廠函式
print(dd[‘a’]) #訪問不存在的key:‘a’
dd = collections.defaultdict(str) #使用str作為工廠函式
print(dd[‘a’]) #訪問不存在的key:‘a’
class Test:
def init(self,name): #只有一個建構函式,而且它有一個引數
print(“init”)
dd = collections.defaultdict(Test) #使用自定義型別Test作為工廠函式
print(dd[‘a’]) #執行到這裡就會出現異常,原因是Test類沒有無參的建構函式
直到最後一行語句之前,上面的結果是:
0
()
第三行是字串的預設值:空字串。
如果不提供工廠函式,那麼預設值的功能就失效了,此時預設字典與普通dict表現的功能一致:
dd = collections.defaultdict()
print(dd[‘a’]) #雖然dd是一個預設字典,但由於沒有指定工廠函式,沒辦法產生一個預設值,因此還是會發生異常
程式設計要求
根據右邊編輯器中各個函式中的提示,將函式Begin-End區間程式碼補充完整,使得程式能夠正常執行並輸出正確的結果。
右側編輯器的4個函式會被依次呼叫,併產生4個預設字典,並會以類似如下的方式,獲取並輸出預設值:
dd = GetIntDefaultDict()
print(“int預設字典的預設值:”,dd[‘a’])
測試說明
正確的補充程式碼後應該得到的結果:
int預設字典的預設值: 0
list預設字典的預設值: []
tuple預設字典的預設值: ()
str預設字典的預設值:
開始你的任務吧,祝你成功!
參考程式碼:

import collections
def GetIntDefaultDict():
    #返回一個空的int型別的預設字典
    # ********** Begin ********** #
    dd = collections.defaultdict(int)
    return dd
    # ********** End ********** #
def GetListDefaultDict():
    #返回一個空的list型別的預設字典
    # ********** Begin ********** #
    dd = collections.defaultdict(list)
    return dd
    # ********** End ********** #
def GetTupleDefaultDict():
    #返回一個空的tuple型別的預設字典
    # ********** Begin ********** #
    dd = collections.defaultdict(tuple)
    return dd 
    # ********** End ********** #
def GetStrDefaultDict(): 
    #返回一個空的str型別的預設字典
    # ********** Begin ********** #
    dd = collections.defaultdict(str)
    return dd
    # ********** End ********** #