使用pop()删除多个项目时出现问题

时间:2018-09-04 12:39:00

标签: python

测试代码:

function=['6005', '6110', '6016', '6104', '6151', '6008', '6112', '6062', '6018', [], '6024', [], '6018', '6012', '6027', '6147', '6028', '6027', '6155', '6004']
empty=[]
for i in range(len(function)):
    if function[i]==' ':
        empty.append(i)
    elif function[i]==[]:
        empty.append(i)
print(empty)
for i in range(len(empty)):
    function.pop(empty[i])
print(function)

我们看到,function [9]和function [11]为空 我成功找到了地址[9, 11](这是第一张照片的地址)

但是我无法从列表中删除这两个元素

我知道了

['6005', '6110', '6016', '6104', '6151', '6008', '6112', '6062', '6018', '6024', [], '6012', '6027', '6147', '6028', '6027', '6155', '6004']

结果,它只是弹出函数[9],但函数[11]仍然存在

为什么会发生以及如何同时删除function [9]和function [11]?

PS:我必须采用这种方式,而不是简单地删除找到的每个“ []”。这只是程序的一部分,我需要使用这些地址来删除另一个列表中的第10和第12个元素。

7 个答案:

答案 0 :(得分:2)

当您弹出第9个元素时,先前的第11个元素将成为第10个元素。因此,在下一次迭代中,您将删除错误的元素。一个简单的解决方法是从最后删除。例如

for i in reversed(empty):
    function.pop(i)

注意:在python中,您不必以C样式进行迭代(例如,对于所有a[i]值都使用i)。您可以直接写for value in values

答案 1 :(得分:1)

一旦弹出索引将被更改,则需要再次运行并将pop用作函数的第二个空列表。

function = [x for x in function if x]

或者:

list(filter(None, function))

或者:

function.pop(9)
function.pop(10) # instead of 11 because index changed.

或使用两次:

function.remove([])

将列表命名为函数是很不好的习惯。

答案 2 :(得分:1)

您不应更改要迭代的列表,否则可能会产生不一致的结果。

一种简单而可靠的方法来获取所需的内容是使用the filter functiona lambda expression以及在布尔上下文中空列表为False的事实:

function = ['6005', '6110', '6016', '6104', '6151', '6008', '6112', '6062',
            '6018', [], '6024', [], '6018', '6012', '6027', '6147', '6028',
            '6027', '6155', '6004']

print filter(lambda item: bool(item), function)
# ['6005', '6110', '6016', '6104', '6151', '6008', '6112', '6062', '6018', '6024', '6012', '6027', '6147', '6028', '6027', '6155', '6004']

@Filiphappy指出,此版本仅过滤空列表,而您的代码也过滤“单个空格字符串”。对于iso功能示例,可以使用以下版本:

print filter(lambda item: item not in (' ', []), function)

答案 3 :(得分:1)

您可以构建一个布尔值列表,说明一个元素是否为空,像这样:

def is_not_empty(x):
    if isinstance(x,str):
        x = x.strip()
    return bool(x)

not_empty = [is_not_empty(x) for x in function]

然后您可以使用itertools.compress过滤列表:

from itertools import compress
function_not_empty = list(compress(function,not_empty))

您还可以使用它来过滤其他列表中的相同元素。

NB-我编辑了此答案,以回应Filip Happy关于缺少单个空格的字符串的评论

答案 4 :(得分:1)

当您删除列表中的第9个元素时,第11个元素将移至第10个元素。当您有更多的空元素时,这将更加复杂。我建议使用

检查空元素来删除它

extra_hosts: - "somehost:162.242.195.82" - "otherhost:50.31.209.229"

上面的代码检查非空元素,并返回您想要的列表。

如果您担心通过索引删除,我建议从头寸降序删除。即,您知道要删除[9,11]个元素,请先删除索引最高的元素。 function = [x for x in function if x]然后function.pop(11)

答案 5 :(得分:1)

您可以使用enumerate,即:

empty_indices = [i for i, x in enumerate(function) if x == [] ]
# [9, 11]

Demo


旧答案:

您可以使用filter从列表中删除空字符串。

new_list = filter(None, old_list)

# ['6005', '6110', '6016', '6104', '6151', '6008', '6112', '6062', '6018', '6024', '6018', '6012', '6027', '6147', '6028', '6027', '6155', '6004']

对于python 3使用:

new_list = list(filter(None, old_list))

注意:

避免使用 function 作为变量名,因为它可能会造成混淆,并且通常被认为是不好的做法。

答案 6 :(得分:0)

删除第一个空列表时,此项目之后的所有内容的索引都会减少一个(此列表现在少1个项目)。因此,您要删除第二个项目,但要插入第二个空列表,就删除了“ 6018”。

您可以进行两个循环,第一个循环查找索引,第二个循环删除空列表:

for i in range(len(function)):
    if function[i]==' ':
        empty.append(i)
    elif function[i]==[]:
        empty.append(i)

i=0  
while(i<len(function)):
    if function[i]==[]:
        del function[i]
        i=i-1
    elif function[i]==' ':
        del function[i]
        i=i-1
    i=i+1