2013-06-18 39 views
1

我有這個python代碼,一個接一個地,整數列表中的項目(在發佈的代碼中名爲'seen')與所有另一個列表的.f字段中的項目(在發佈的代碼中名爲'maxx')。 在每次迭代時,我都會計數(通過'c'變量)第j個項目出現在'maxx'列表中的次數,如果它出現少於三次,我想從列表中彈出()它倍。 該代碼完美地工作,但是彈出一個項目'將'看到'列表中的任何後續項目拉回到一個位置,因此每當if條件滿足時,循環就會錯過列表的下一個項目。 我想不出有辦法解決這個問題,有什麼想法?PYTHON - 'for'索引由於list.pop()調用而改變

謝謝。

下面是代碼:

for indj,j in enumerate(seen): # every item in the 'seen' list.. 
    c=0 
    for k in maxx:    # ..checks for a matching item in the 'maxx' list 
     if j==k.f: 
      c=c+1; 
    if c<3:      # if the item appears less than 3 times we pop it 
     seen.pop(indj) 

編輯:忘了說我試圖在if結構的末尾添加

indj=indj-1 
j=seen[indj] 

,但沒有奏效

+0

改變原來的列表迭代之前,確保已看到副本:'爲indj,j枚舉(見[:]):'。這在Python教程中有描述。 – michaelmeyer

回答

2

您必須創建一個新列表或使用副本進行工作。當您在循環播放列表時更改列表時,可以跳過一些項目。我應該這樣做:

def filter_low(lst, maxk, threshold=3): 
    for item in lst: 
     c = sum(1 for k in maxx if item==k.f) 
     if c >= threshold: 
      yield item 


new_seen = list(filter_low(seen, maxk, 3)) 

這是一樣的:

new_seen = [item for item in seen 
      if sum(1 for k in maxx if item==k.f) >= 3] 

您可以通過執行

seen[:] = [item for item in seen 
      if sum(1 for k in maxx if item==k.f) >= 3] 
+0

嘿,這實際上做了伎倆(用一行),你爲什麼得到一個downvote?創建一個全新的名單不雅觀嗎?不管怎麼說,還是要謝謝你。 – Tom

1

修改你正在迭代的列表從來不是一個好主意。你可以遍歷一個副本,並與

popped = 0 
for indj, j in enumerate(seen[:]): 
    s = sum(j == k.f for k in maxx) 
    if s < 3: 
     seen.pop(indj - popped) 
     popped += 1 

修改實際的列表。如果seen列表是非常大的,這可能是低效的。

+0

通過在'seen'後加上[[:]',代碼可以正常工作(不會跳過任何項目),但一旦到達列表的後半部分,就會給出'IndexError:pop index超出範圍'。 – Tom

+0

啊,當然。將代碼調整爲新版本。請嘗試一下。 –

+0

你的代碼現在工作正常,謝謝! – Tom