2015-05-11 56 views
1

我有一個列表:[1,2,3,4,5,6,0,9,2],我想循環。循環列表直到找到值然後中斷?

我想直到我達到0元件(即,第一詞典將會{'gold':1,'silver':2,'bronze':3}同樣地,對於4,5,6)來創建字典對於每3個元件的另一列表。該循環將自達到0後終止。

所以,最終名單將是:[{'gold':1,'silver':2,'bronze':3},{'gold':4,'silver':5,'bronze':6}]

作爲新的Python和PHP的背景的,我將如何解決像zipmap這個槓桿功能或我必須while循環訴諸平原?

+0

你是否知道一個3個元素中的第一個元素總是會出現一個零?如果它不應該把這個三元組列入清單? –

+0

不,零可以出現在任何地方,如果一個字典包含一個零,它將被丟棄並且循環終止。 –

+0

@VeraWang,鑰匙的順序呢? –

回答

2
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

請從迭代只要謂詞是返回元素的迭代器真正。

所以我們只需要元素,直到我們遇到的第一個id = 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而不是過濾器。

+0

你的第一個'groups'函數,爲什麼沒有返回語句? –

+0

@VeraWang,因爲當每個字典的len等於'n'時,我們正在屈服,否則我們只是打破循環,因爲我們在末尾有一個字典,沒有三個元素,因爲第一個0在索引處那不是3的倍數。你可以循環訪問'groups(l,keys,0,3))'並且隨時獲得每個字典,你不必調用列表並將所有的字典列表存儲在內存中,這就是使用發電機。 –

+0

如果你想擁有帶'n'鍵的字典,你需要檢查每個字母的長度,答案第二部分的輸入將會在結尾 –

1

簡單!用一個簡單的功能,數據結構和簡單的迭代:

例子:

from collections import defaultdict 


def f(xs, labels=("gold", "silver", "bronze")): 
    d = defaultdict(int) 
    n = 0 
    for i, x in enumerate(xs): 
     if x == 0: # break if we see a 0 
      return d 

     d[labels[n]] += i # update our counts 

     # cycle through gold/silver/bronze (labels) 
     n += 1 
     if n % 3 == 0: 
      n = 0 

    return d 


xs = [1, 2, 3, 4, 5, 6, 0, 9, 2] 
d = f(xs) 
print d 

輸出:

$ python foo.py 
defaultdict(<type 'int'>, {'bronze': 7, 'silver': 5, 'gold': 3}) 
+0

我不確定是否改變我的迴應,以根據@ John的回答產生一個字典序列:)看起來這就是這裏的主意! –

4
from itertools import cycle 

placings = cycle(['gold', 'silver', 'bronze']) 
numbers = [1,2,3,4,5,6,0,9,2] 

def zipper(numbers, placings): 

    d = {} 

    for n, c in zip(numbers, placings): 

     if n == 0: 
      break 

     d[n] = c 

     if n % 3 == 0: 
      yield d 
      d = {} 

print list(zipper(numbers, placings)) 
+1

不錯的@John :)很好用的功能性編程! –

+0

@詹姆斯米爾斯謝謝! – John

+0

@JamesMills我將你的編輯從'return d'改爲'return None',因爲它有可能返回一個部分完成的字典,那將是一個不好的行爲。經過一些[研究](http://stackoverflow.com/questions/4027586/is-it-ok-to-skip-return-none)我同意函數應該可能明確地返回一些東西。 – John

1

你首先需要突破大列入與列表medals相同大小的較小列表中,以使zip() func並且列表中的0的位置應位於可被列表的長度整除的位置,否則小列表中的最後列表將具有更少的元素數量。

listOfDictionary = [] 
lst = [1,2,3,4,5,6,0,9,2] 

ind = lst.index(0) #Tells where to break the iteration loop. 

medals = ["gold", "silver", "bronze"] 

if ind%3==0: 

    newlst = [lst[i: i+3]for i in xrange(0,ind,3)] 
    #newlst = [[1, 2, 3], [4, 5, 6]] 

    for lsst in newlst: 
     listOfDictionary.append(dict(zip(medals, lsst))) 


print listOfDictionary 
>>> [{'bronze': 3, 'silver': 2, 'gold': 1}, {'bronze': 6, 'silver': 5, 'gold': 4}] 
1

在列表的情況下,使用列表理解,然後用循環

In [61]: mykeys 
Out[61]: [1, 2, 3, 4, 5, 6, 0, 9, 2] 

In [63]: mykeys1=[i for i in mykeys[:-1 if 0 not in mykeys else mykeys.index(0)]] 

In [64]: myvalues 
Out[64]: ['gold', 'silver', 'bronze'] 

In [66]: myvalues1=cycle(myvalues) 

In [67]: mydict=dict(zip(mykeys1,myvalues1)) 

In [68]: mydict 
Out[68]: {1: 'gold', 2: 'silver', 3: 'bronze', 4: 'gold', 5: 'silver', 6: 'bronze'} 
In [69]: [dict(mydict.items()[i:i+3]) for i in range(0,len(mykeys1),3)] 
Out[69]: [{1: 'gold', 2: 'silver', 3: 'bronze'}, {4: 'gold', 5: 'silver', 6: 'bronze'}] 
+0

This創建一個單詞 –

+1

@ Padraic坎寧安謝謝..我想問題被修改..我沒有看到..謝謝...順便說一句你的答案是最優雅的,我會選擇它作爲anwser – Ajay