【问题标题】:Python: Removing negatives from a list of numbersPython:从数字列表中删除负数
【发布时间】:2014-01-24 10:43:44
【问题描述】:

问题是从数字中删除负数。

remove_negs([1, 2, 3, -3, 6, -1, -3, 1])执行时,结果为:[1, 2, 3, 6, -3, 1]。结果假定为[1, 2, 3, 6, 3, 1]。发生的情况是,如果连续有两个负数(例如,-1, -3),那么第二个数字将不会被删除。 定义主(): numbers = input("请输入数字列表:") remove_negs(数字)

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()

【问题讨论】:

  • 对于检查 val >= 0 的列表理解来说,这听起来不错。
  • 不要从您正在迭代的列表中删除项目,因为这会更改项目的索引,您最终可能会跳过某些元素。
  • 正如其他人所说,在迭代数据容器时不要更改它的内容。迭代一个副本 - 对于列表中的项目(num_list):
  • 另外,当您已经知道某个项目在哪里时,您不应该调用remove 来删除它。这(a)可能是错误的,因为remove 删除了等于item 的第一个项目,这可能不是您想要的,并且(b)很慢,因为这意味着您必须搜索整个列表才能找到即使您已经知道它在哪里。 del num_list[index] 总是更好。但是你怎么知道索引?很简单:for index, item in enumerate(num_list):。 (这只是一个旁注;它不会解决你的实际问题……但已经有很好的答案和 cmets 了。)

标签: python list negative-number


【解决方案1】:

简单得多:

>>> 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]

【讨论】:

    【解决方案2】:

    在迭代列表时从列表中删除元素通常是一个坏主意(请参阅我的评论中的 the link 以了解为什么会这样)。更好的方法是使用list comprehension:

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

    请注意,上面的行创建了一个 new 列表并将num_list 分配给该列表。您还可以对表单进行“就地”分配

    num_list[:] = ...
    

    它不会在内存中创建新列表,而是修改num_list 已经指向的内存位置。这个区别在here有更详细的解释。

    【讨论】:

    • 我认为 OP 实际上不需要在这里改变num_list,所以原始版本(没有切片分配)可能没问题。也许将两者都展示并解释差异会更好?
    • @abarnert 是的,也许你是对的。我将进行编辑以解释差异。
    • @user3161743:你说“结果应该是[1, 2, 3, 6, 3, 1]。”这正是 arshajii 的代码所产生的。如果您按照您声称想要的方式进行操作,结果将是 [1, 2, 3, 3, 6, 1, 3, 1]
    【解决方案3】:

    来自对 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],这是错误的答案……但如果你的评论是正确的,那就是你要求的答案。

    【讨论】:

      【解决方案4】:

      其他的常规variable operator non-variable也试试yoda conditions=)

      >>> [i for i in x if 0 <= i]
      [1, 2, 3, 6, 1]
      

      【讨论】:

        【解决方案5】:

        去除数字的负号,这是最简单的方法

        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]

        【讨论】:

          【解决方案6】:

          另一种解决方案

          filter( lambda x: x>0, [ 1, 2, 3, -3, 6, -1, -3, 1])
          [1, 2, 3, 6, 1]
          

          【讨论】:

            【解决方案7】:

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

            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
            

            【讨论】:

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2015-06-23
                • 2017-05-07
                • 1970-01-01
                • 2013-10-21
                • 2016-08-26
                • 1970-01-01
                相关资源
                最近更新 更多