from itertools import takewhile, islice
def groups(l, keys, i, n):
# lambda x: x != 0 -> take elements until we encounter any 0
tk = takewhile(lambda x: x != i, l)
while True:
d = dict(zip(keys, islice(tk, n)))
if len(d) == n: # make sure we have n keys in the dict
yield d
else:
break
keys = ['gold', 'silver', 'bronze']
print(list(groups(l,keys,0,3)))
[{'bronze': 3, 'gold': 1, 'silver': 2}, {'bronze': 6, 'gold': 4, 'silver': 5}]
takewhile
請從迭代只要謂詞是返回元素的迭代器真正。
所以我們只需要元素,直到我們遇到的第一個i
,d = islice(tk,n)
需要n
長片使用我們takewhile對象,我們再從鍵通過創建一個字典,創建字典消耗在n
元素每次我們調用它時,我們都會轉向接下來的三個元素。如果takewhile對象的長度不是n
的倍數,那麼我們將在末尾有一個字典,它小於n
的大小,因此if len(d) == n:
會捕獲該字符並打破循環,所以奇數長度字典或空字典將終止這段時間。
如果允許類型的字典少於三個按鍵:
from itertools import takewhile, islice,chain
def groups(l, keys, i, n):
tk = takewhile(lambda x: x != i, l)
return (dict(zip(keys, chain(islice(tk, n - 1),(i,)))) for i in tk)
輸出:
In [5]: l = [1, 2, 3, 4, 5, 6, 7, 11, 6, 9, 0, 2]
In [6]: list(groups(l,['gold', 'silver', 'bronze'],0,3))
Out[6]:
[{'bronze': 1, 'gold': 2, 'silver': 3},
{'bronze': 4, 'gold': 5, 'silver': 6},
{'bronze': 7, 'gold': 11, 'silver': 6},
{'gold': 9}]
islice(tk, n - 1)
需要切片從我們takewhile對象LEN N - 1,我們鏈中和i
所以我們每次獲得n
個元素。
或者使用過濾器濾除字典少於3個按鍵:
def groups(l, keys, i, n):
tk = takewhile(lambda x: x != i, l)
return filter(lambda x: len(x) == n, (dict(zip(keys, chain(islice(tk, n - 1),(i,))))
for i in tk))
從而消除較短的字典:
In [8]: list(groups(l,['gold', 'silver', 'bronze'],0,3))
Out[8]:
[{'bronze': 1, 'gold': 2, 'silver': 3},
{'bronze': 4, 'gold': 5, 'silver': 6},
{'bronze': 7, 'gold': 11, 'silver': 6}]
這並不等同於以前我們只是過濾任何潛在的從結尾開始奇數長度的字典。對於python2,使用itertools.ifilter
而不是過濾器。
你是否知道一個3個元素中的第一個元素總是會出現一個零?如果它不應該把這個三元組列入清單? –
不,零可以出現在任何地方,如果一個字典包含一個零,它將被丟棄並且循環終止。 –
@VeraWang,鑰匙的順序呢? –