Python:从数字列表中删除负数

8
问题是从数字中删除负数。
当执行remove_negs([1, 2, 3, -3, 6, -1, -3, 1])时,结果为:[1, 2, 3, 6, -3, 1]。结果应该是[1, 2, 3, 6, 3, 1]。问题在于如果有两个负数连续出现(例如-1,-3),则第二个数字将不会被删除。
def main(): numbers = input("输入一组数字:") remove_negs(numbers)
def remove_negs(num_list): 
  '''Remove the negative numbers from the list num_list.'''
    for item in num_list: 
        if item < 0: 
           num_list.remove(item) 

    print num_list

main()

1
听起来像是一个很适合使用列表推导式的工作,它可以检查val是否大于等于0。 - Dogweather
2
不要从你正在迭代的列表中删除元素,因为这会改变这些元素的索引,你可能会跳过其中一些元素。 - kylieCatt
1
正如其他人所说,当您在迭代数据容器时,请勿更改其内容。请对副本进行迭代 - for item in list(num_list): - macfij
2
另外,当你已经知道目标位置时,不应该调用“remove”来删除元素。这样做的原因是:(a) 可能会出错,因为“remove”将删除与“item”相等的第一个项目,而这可能不是你想要的;(b) 这样做很慢,因为这意味着你必须搜索整个列表以找到项目,即使你已经知道它在哪里。“del num_list[index]”总是更好的选择。但是,如何知道索引?简单:使用“for index, item in enumerate(num_list):”。(这都是一些注意事项;这并不能解决您实际的问题......但是已经有了良好的答案和评论来解决这个问题。) - abarnert
8个回答

15

在迭代列表时从中删除元素通常不是个好主意(参见我的评论中的链接,了解其中的原因)。更好的方法是使用列表推导式

num_list = [item for item in num_list if item >= 0]

注意上面的代码创建了一个的列表并将num_list赋值给它。你也可以采用“原地”赋值形式,例如:

num_list[:] = ...

这并不会在内存中创建一个新的列表,而是修改已经被 num_list 指向的内存位置。关于这种区别的详细解释可以在这里找到。


我认为原帖作者实际上不需要在这里改变num_list,因此原始版本(没有切片赋值)可能已经很好了。或许最好展示两种方式并解释它们的不同之处? - abarnert
@abarnert 是的,也许你是对的。我会编辑一下来解释这个区别。 - arshajii
1
@user3161743:你说“结果应该是[1, 2, 3, 6, 3, 1]。”这正是arshajii的代码所产生的。如果你按照你所声称的方式进行操作,那么结果将会是[1, 2, 3, 3, 6, 1, 3, 1] - abarnert

13

简单得多:

>>> a = [ 1, 2, 3, -3, 6, -1, -3, 1]
>>> [x for x in a if x >= 0 ]
[1, 2, 3, 6, 1]

如果你真的想要循环,可以尝试这样:

def remove_negs(num_list): 
    r = num_list[:]
    for item in num_list: 
        if item < 0: 
           r.remove(item) 
    print r

这个做你想要的事情:

>>> remove_negs([ 1, 2, 3, -3, 6, -1, -3, 1])
[1, 2, 3, 6, 1]

r = num_list[:]是关键,它创建了num_list的一个副本。为了避免混淆循环,我们从r中删除项目,而不是从正在循环的列表中删除。

更多信息:Python对变量的处理有些微妙。Python将变量名(如rnum_list)与变量数据(如[1, 2, 3, 6, 1])分开存储。变量名只是指向数据的指针。考虑以下赋值语句:

r = num_list
运行此语句后,rnum_list都指向相同的数据。 如果您更改r的数据,则也会更改num_list的数据,因为它们都指向相同的数据。现在考虑:
r = num_list[:]
这个语句告诉Python只修改num_list的数据,通过选取其中一些元素来实现。因此,Python会复制num_list的数据。正好[:]指定我们希望所有num_list的数据不变,但这并不会阻止Python复制。复制品被赋给r。这意味着rmum_list现在指向不同的数据。我们可以更改r的数据,而不影响num_list的数据,因为它们具有不同的数据。
如果您还不了解这一点,您可能需要查看关于Python变量名称和变量数据的教程:Understanding Python variables and Memory Management 示例:
>>> a = [ 1, 2, 3, -3, 6, -1, -3, 1]
>>> b = a   # a and b now point to the same place
>>> b.remove(-1) 
>>> a
[1, 2, 3, -3, 6, -3, 1]

相对比:

>>> a = [ 1, 2, 3, -3, 6, -1, -3, 1]
>>> b = a[:] # a and b now point to different data
>>> b
[1, 2, 3, -3, 6, -1, -3, 1]
>>> b.remove(-1)
>>> b
[1, 2, 3, -3, 6, -3, 1]
>>> a
[1, 2, 3, -3, 6, -1, -3, 1]

5
另一种解决方案
filter( lambda x: x>0, [ 1, 2, 3, -3, 6, -1, -3, 1])
[1, 2, 3, 6, 1]

1

以下是对arshajii答案评论的回复:

但这会删除负数。我需要删除负号,但仍然保留列表中的数字。

从您的代码清晰地尝试要做的事情来看,删除负数正是您的代码所要做的,也是获得所需结果的唯一方法:

结果应该是 [1, 2, 3, 6, 3, 1]

但如果您真的想要“删除数字中的负号”,那就更容易了。例如,要从-3中删除负号,您只需取反它并得到3,对吧?您可以在原地执行此操作,就像您现有的代码一样:

for index, item in enumerate(num_list): 
    if item < 0: 
       num_list[index] = -item

…或者在列表推导式中,例如arshajii的方法:

num_list = [-item if item < 0 else item for item in num_list]

使用abs函数更加简单,它可以将负数取反,保留正数和零:

num_list = [abs(item) for item in num_list]

当然,无论如何,这都会给你[1, 2, 3, 3, 6, 1, 3, 1],这是错误的答案...但如果你的评论是正确的,那么它就是你要求的答案。

1
除了传统的“变量运算符非变量”,也可以尝试一些yoda条件哦 =)
>>> [i for i in x if 0 <= i]
[1, 2, 3, 6, 1]

1
我认为一个优雅的解决方案可以是这样的:

import numpy as np

x = [1, 2, 3, -3, 6, -1, -3, 1] # raw data
x = np.array(x) # convert the python list to a numpy array, to enable 
                  matrix operations 
x = x[x >=0] # this section `[x >=0]` produces vector of True and False 
               values, of the same length as the list x
             # as such, this statement `x[x >=0]` produces only the 
               positive values and the zeros

print(x)   
[1 2 3 6 1] # the result

0

去掉数字的负号,这是最简单的事情。

def remove_negs(somelist):
    for each in somelist:
        if each < 0:
            somelist[somelist.index(each)] = -each
    print(somelist)

例如:

rNegatives([-2,5,11,-1])

将输出

[2,5,11,1]


0
A=[1,2,-3,5,-8,-22,-4,6,9,-12]
B=list(filter(lambda x: x >= 0, A))
print(B)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接