繁体   English   中英

如何在 python 中使用 for 循环在没有列表理解的情况下从列表中弹出所有负数

[英]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.

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