[英]Pop() used in a comprehension list not removing all items from initial list
[英]how to pop all negative numbers from list with for loop without list comprehension in python
我收到一条错误消息,说“Traceback(最近一次调用最后一次):文件“main.py”,第 10 行,如果 list1[j] < 0:IndexError:列表索引超出范围”
我试图从样本输入“10 -7 4 39 -6 12 2”中删除所有负数,以制作像这样的 output 10 4 39 12 2 尝试使用 pop 来执行此操作。
我无法找到一个确切的解决方法,我通过谷歌搜索并在stackoverflow上搜索。
我不希望列表理解作为答案
input1 = str(input())
list1 = input1.split()
for i in range(len(list1)):
list1[i] = int(list1[i])
for j in range(len(list1)):
if list1[j] < 0:
list1.pop(j)
print(list1)
你为什么要使用pop
? 由于您没有保存该值,因此您可能应该使用del list1[index]
。
在任何情况下,在迭代时修改列表都是 1) 正确执行令人讨厌 2) 效率非常低。 相反,您应该使用列表理解或常规循环创建一个新列表。
根本问题是,当您删除一个项目时,之后的所有索引都已移动。
天真地,您可能认为您可以执行以下操作:
for i, e in enumerate(data):
if e < 0:
del data[i]
这不会引发索引错误,但是,如果您有两个相邻的负数,它将跳过一个:
>>> data = [1,2, -3, -4, 5]
>>> for i,e in enumerate(data):
... if e < 0:
... del data[i]
...
>>> data
[1, 2, -4, 5]
>>>
但是这里有几种方法可以做到。
首先,只需跟踪您已删除的项目数量并相应地调整索引:
>>> removed = 0
>>> data = [1,2, -3, -4, 5]
>>> for i in range(len(data)):
... if data[i - removed] < 0:
... del data[i - removed]
... removed += 1
...
>>> data
[1, 2, 5]
也许最简单的方法是使用一个while循环,实际上:
>>> data = [1,2, -3, -4, 5]
>>> i = 0
>>> while i < len(data):
... if data[i] < 0:
... del data[i]
... else:
... i += 1
...
>>> data
[1, 2, 5]
上面的重点是仅在您不删除某些内容时才增加i
。
最后,您可以简单地从列表末尾开始迭代:
>>> data = [1,2, -3, -4, 5]
>>> for i in reversed(range(len(data))):
... if data[i] < 0:
... del data[i]
...
>>> data
[1, 2, 5]
>>>
重申:
它们需要线性空间和二次时间。 您可以在线性空间和线性时间中创建一个新列表。
考虑:
>>> data = [1,2, -3, -4, 5]
>>> new_data = []
>>> for x in data:
... if x >= 0:
... new_data.append(x)
...
>>> new_data
[1, 2, 5]
或等效的列表理解:
>>> data = [x for x in data if x >= 0]
>>> data
[1, 2, 5]
代码:
input1 = str(input())
list1 = input1.split()
ind_to_remove = []
for i in range(len(list1)):
list1[i] = int(list1[i])
if list1[i] < 0:
ind_to_remove.append(i)
ind_to_remove.sort(reverse=True)
for ind in ind_to_remove:
list1.pop(ind)
print(list1)
列表理解可能是最佳实践,但是如果没有列表理解,您可以这样做。 您正在做的是迭代初始列表的长度,但 pop 正在缩小您的列表,以便原始索引不再适用于列表(因此出现错误)。
一种方法是在列表中使用.remove
。 这将删除与该值匹配的第一个元素,这将在这种情况下起作用。 这更像是一个 hack,因为我们使用list()
function 来返回列表的副本,以便在我们修改它时迭代副本并从列表中获取每个值。 如果我们不创建副本,循环将跳过一些值。 如果您不想要列表理解或创建新列表,这可能比此处发布的其他方法更干净(但是,您实际上是使用此方法在内存方面创建新列表)。
lst = ["1", "-3", "-5", "-3", "10", "10", "11", "-4"]
for val in list(lst):
if int(val) < 0:
lst.remove(val)
else:
lst[lst.index(val)] = int(val)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.