2015-04-17 82 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] 

拆分,而不会丢失任何信息