简体   繁体   English

Python忽略命令从列表中删除项目

[英]Python ignoring command to remove items from list

I'm filtering through a very large list of dictionaries. 我正在筛选大量词典。 kept is the global list and it has about 9000 dictionaries within it and all the dictionaries have the same keys. kept是全局列表,其中包含大约9000个字典,所有字典都具有相同的键。 I'm trying to remove every dictionary that has a 'M_P' values greater than -4.5 and there are more than half of them so I created a function solely for his purpose. 我正在尝试删除所有'M_P'值大于-4.5的字典,并且其中一半以上,因此我仅为他的目的创建了一个函数。 WHen I check to see if they have all been removed in a later function, there are still ~3000 left. 当我检查一下是否在以后的功能中将它们全部删除时,仍然还有〜3000。 Can anybody tell me why that would be happening and can I trust that these functions will do what I am telling it to do? 谁能告诉我为什么会发生这种情况,我是否可以相信这些功能将按照我的指示去做?

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

Right here is where I'm checking it. 就在这里,我正在检查它。 ^^^ ^^^

        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

The output for the following is like 3000. 以下输出类似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"
'''

When iterating using a for loop, Python doesn't automatically make a copy of the list, but iterates on it directly. 使用for循环进行迭代时,Python不会自动创建列表的副本,而是直接对其进行迭代。 So, when you remove an element, the loop won't take the change into account and will skip elements of the list. 因此,当您删除一个元素时,循环将不会考虑更改,并且会跳过列表中的元素。

Example: 例:

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

You can use an list indice as shorthand to make a copy of the list before iterating, for example: 您可以使用列表索引作为速记,以在迭代之前制作列表的副本,例如:

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

As others have said, you are modifying an array while iterating over it. 正如其他人所说,您在迭代数组时正在修改它。

The simple one-liner for this would be 一个简单的单线是

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

Which simply keeps all the entries you are interested in, replacing the original list. 只需保留您感兴趣的所有条目,即可替换原始列表。

Calculating how many were removed is simply a matter of taking len(kept) before and after the comprehension and taking the difference. 计算除去的数量仅是在理解前后取len(kept)并取其差值即可。

Alternatively, 或者,

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]

Splits the array without losing any information 拆分数组而不会丢失任何信息

You should never modify the sequence you are iterating over in a for loop. 您永远不要修改for循环中要迭代的序列。 Looking just at your first function: 看一下您的第一个功能:

def removeMag():

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

You are calling remove on kept in the loop. 您正在呼吁remove关于kept在环。 This leads to unspecified behaviour and anything can happen. 这会导致未指定的行为,并且可能发生任何事情。 See this question . 看到这个问题

A simple way to solve this is to use a new list for the items to keep: 解决此问题的一种简单方法是对要保留的项目使用新列表:

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

kept = mag_to_keep

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM