2015-04-17 85 views
-1

我正在通過非常大的字典列表進行篩選。 kept是全球名單,它內有大約9000個字典,所有字典都有相同的密鑰。我試圖刪除'M_P'值大於-4.5的每個字典,並且其中有一半以上的字典,所以我創建了一個僅用於他的目的的函數。當我檢查它們是否在後面的功能中被全部刪除時,仍然有〜3000左右。任何人都可以告訴我爲什麼會發生這種情況嗎?我可以相信這些功能會按我所說的去做嗎?Python忽略命令以從列表中刪除項目

def removeMag(): 

    countMag = 0 
    for mag in kept: 
     if to_float(mag['M_P']) > -4.5: 
      kept.remove(mag) 
      countMag += 1 
     else: 
      continue 

    print '\n' 
    print ' Number of mags > -4.5 actually removed: ' 
    print countMag 

def remove_anomalies():  
    count = 0 
    count08 = 0 
    count09 = 0 
    count01 = 0 
    countMag = 0 
    countMagDim = 0 
    #Want to remove Q* < 15 degrees 
    for row in kept: 
     #to_float(kept(row)) 
     #Q* greater than 15 
     if to_float(row['Q*']) < 15.00: 
      kept.remove(row) 
     elif to_float(row['vel']) > 80.00: 
      kept.remove(row) 
     elif to_float(row['err']) >= 0.5*to_float(row['vel']): 
      kept.remove(row) 

     elif row['log_10_m'] == '?': 
      kept.remove(row) 
      #print row 
      count+=1 
     elif row['M_P'] == '?': 
      kept.remove(row) 
      countMag += 1 
     elif to_float(row['M_P']) > -4.5: 
      countMagDim += 1 

就在這裏,我正在檢查它。 ^^^

 elif to_float(row['T_j']) < -50.00 or to_float(row['T_j'] > 50.00): 
     kept.remove(row) 
     count01 += 1 

     #make sure beg height is above end height. 
     elif to_float(row['H_beg']) < to_float(row['H_end']): 
      kept.remove(row) 
     #make sure zenith distance is not greater than 90 
     elif to_float(row['eta_p']) > 90.00: 
      kept.remove(row) 
     #Remove extremities hyperbolic orbits  
     elif (to_float(row['e']) > 2.00 and to_float(row['e']) == 0.00 and to_float(row['a']) == 0.00 and to_float(row['incl']) == 0.00 and to_float(row['omega']) == 0.00 and to_float(row['anode']) == 0.00 and to_float(row['alp_g']) == 0.00 and to_float(row['del_g']) == 0.00 and to_float(row['lam_g']) == 0.00 and to_float(row['bet_g']) == 0.00): 
      kept.remove(row) 
      count08+=1 
     elif to_float(row['q_per']) == 0.00: 
      kept.remove(row) 
      count09+=1 
     elif to_float(row['q_aph']) == 0.00: 
      kept.remove(row) 
      count09+=1 
     else: continue 

    print 'Number of dicts with ? as mass value:' 
    print count  

    print " Number removed with orbital elements condition: " 
    print count08 

    print "Number of per or aph equal to 0: " 
    print count09 

    print "Number of T_j anomalies: " 
    print count01 

    print "Number of Magnitudes removed from '?': " 
    print countMag 

以下的輸出是像3000

print "Number of Magnitudes to be removed from too dim: " 
    print countMagDim 
'''  
    print "\n" 
    print "log mass values:" 
    for row2 in kept: 
     print row2['log_10_mass'] 
    print "\n" 
''' 
+2

你從清單中移除您當前迭代項目的數組。這會產生一些意想不到的行爲。 – Jkdc

+0

https://asmeurersympy.wordpress.com/2009/07/20/modifying-a-list-while-looping-through-it-in-python/ – dbliss

+0

謝謝大家!我不知道這一切,我很感激! – spacedancechimp

回答

1

你不應該修改你迭代的序列在for循環中結束。只是看你的第一個功能:

def removeMag(): 

    countMag = 0 
    for mag in kept: 
     if to_float(mag['M_P']) > -4.5: 
      kept.remove(mag) 
      countMag += 1 

您在環路上kept調用remove。這會導致不確定的行爲,任何事情都可能發生。請參閱this question

一個簡單的方法來解決這個問題是使用一個新的列表中的項目,以保持:

mag_to_keep = [] 
for mag in kept: 
    if float(mag['M_P']) <= -4.5: 
     mag_to_keep.append(mag) 

kept = mag_to_keep 
5

當迭代使用for循環,巨蟒不會自動使該列表的副本,但它直接迭代。所以,當你刪除一個元素時,循環不會考慮這個變化,並且會跳過列表中的元素。

例子:

>>> l = [1,2,3,4,5] 
>>> for i in l: l.remove(i) 
>>> l 
[2, 4] 

您可以使用列表指數之速記使列表的副本迭代之前,例如:

>>> for i in l[:]: l.remove(i) 
>>> l 
[] 
2

正如其他人說,你在遍歷它修改陣列。

的簡單的一行因爲這將是

kept = [mag for mag in kept if to_float(mag['M_P']) <= -4.5] 

它只是保留了所有你感興趣的項目,取代了原來的列表中。

計算被刪除的人數僅僅是在理解之前和之後採取len(kept)並考慮差異。

另外,

discarded = [mag for mag in kept if to_float(mag['M_P']) > -4.5] 
kept = [mag for mag in kept if to_float(mag['M_P']) <= -4.5] 

拆分,而不會丟失任何信息