【问题标题】:Removing Negative Numbers from a list Python using while loop使用while循环从Python列表中删除负数
【发布时间】:2015-06-23 20:14:47
【问题描述】:

rmNegative(L)list L 中删除负数,假设仅包含数字元素。 (修改 L;不创建新列表。)

当使用 while 循环时,我将如何处理这个问题?我一遍又一遍地尝试编码,我得到的只是一个永无止境的循环..

def rmNegatives(L):
    pos=len(L)-1
    while pos>-1:
        pos=pos
        if pos<len(L)-1:
            pos=pos
            if L[pos]>0:
                L[:]=L[:]
                pos=len(L)-2
            elif L[pos]<0:
                L[:]=[L[pos]]+L[0:]
                L[:]=L[1:]
                pos=len(L)-1

        elif pos==len(L)-1:
            pos=pos
            if L[pos]<0:
                L[0:]=L[0:pos]
                pos=len(L)-1
            elif L[pos]>0:
                L[:]=L[:]
                pos=len(L)-2

rmNegatives([-25,31,-10,23,45,-2])

Run the code here

编辑** 感谢您的回复。我的代码不包含任何形式的删除或索引的原因是因为我被限制使用它们(如果不使用它们会很好,但是......)

【问题讨论】:

  • 您的列表对我不起作用,没有显示代码。你可以把你的代码放在你的帖子中。
  • 我编辑了它,当然等待批准。
  • 看起来第一个块是评论?我在第一次编辑时错过了'''。也许最好只显示将运行的代码?
  • 您希望我们调试您现有的代码吗?我真的不确定大部分是试图做什么,所以很难说哪里出了问题。例如,您希望pos = posL[:] = L[:] 做什么?为什么pos=len(L)-2

标签: python list while-loop negative-number


【解决方案1】:

好吧,现在不分配新列表,

>>> list_l = [1, -1, 2, -8]

>>> length = len(list_l)
>>> while i < length:
...     if list_l[i] < 0:
...             del list_l[i]
...             length -= 1
...     else:
...             i = i + 1
... 
>>> list_l
[1, 2]

【讨论】:

  • 这会创建一个新列表并覆盖旧的引用。使用循环可能是课程的一部分。
  • 现在请告诉我,我在哪些方面犹豫不决,值得投反对票。
  • @pnv:通常在没有 cmets 的情况下投反对票的人在您编辑后再也不会回来查看。因此,即使 TigerhawkT3 取消了他的反对票(我不知道他是否这样做了……),您也可能不会让其他 2 人回来。而且我不希望得到太多支持,因为您的新正确版本不会添加任何其他答案中没有的任何内容。因此,如果您真的担心代表,您可能只想删除答案。
  • 指出,但绝对不会删除。 :)
【解决方案2】:

这是我对rmNegative(L) 的实现。

def rmNegative(L):
    m = min(L)
    while m < 0:
        L.remove(m)
        m = min(L)

这会修改列表,但不会创建新列表。

【讨论】:

    【解决方案3】:

    这是一个带有 while 循环的实现。我从最后开始,因为随着循环的迭代,列表变得越来越短,结果更早的索引正在移动。

    def rmNegative(L):
        index = len(L) - 1
        while index >= 0:
            if L[index] < 0:
                del L[index]
            index = index - 1
    

    【讨论】:

    • 从末尾开始意味着您不需要一直检查len。不使用remove 意味着不教坏习惯(并且不会产生二次表现)。但是……您从L[len(L)] 开始,而不是L[len(L)-1],后者是IndexError。并且 - 4 代替 - 1 不是一个好主意。
    • @abarnert 这就是我在另一个窗口中重新输入的内容。我不知道我是怎么打错-4的。这当然不是故意的。谢谢你抓住那些。我已经编辑了。
    【解决方案4】:

    如果您绝对负担不起创建新列表并且必须使用while 循环:

    l = [1,2,3,-1,-2,-3,4,5]
    x = 0
    while x < len(l):
      if l[x] < 0:
        l.remove(l[x])
        continue
      x += 1
    

    或者,按照 abarnert 的建议(较低的运行时间):

    l = [1,2,3,-1,-2,-3,4,5]
    x = 0
    while x < len(l):
      if l[x] < 0:
        del l[x]
        continue
      x += 1
    

    如果您绝对负担不起创建新列表,但可以使用for 循环:

    l = [1,2,3,-1,-2,-3,4,5]
    for x in xrange(len(l)):
      if x < len(l) and l[x] < 0:
        l.remove(l[x])
    

    如果您有能力创建一个新列表:

    l = [1,2,3,-1,-2,-3,4,5]
    l = [num for num in l if num >= 0]
    

    【讨论】:

    • 使用remove 是个坏主意。它在这里确实有效,因为删除“错误”-1 并不重要,因为无论如何你最终都会删除所有这些。但学习它仍然是一个坏习惯。更不用说无缘无故地给出二次性能而不是线性。
    【解决方案5】:

    您首先需要知道的是del L[i] 删除了ith 元素。 (不要使用L.remove(L[i]);它会查找ith 元素,然后搜索整个列表,直到找到相等的值,然后将其删除。)

    但是请注意,如果您删除L[3],然后转到L[4],您就跳过了一个值——原来的L[4] 现在是L[3],您仍然需要检查它。因此,您必须确保在找到要保留的值之前不要增加 i

    但是,如果您只是遍历所有索引,并且一路删除了一些索引,那么您将跑到最后。因此,每次删除时都需要减少长度。或者您也可以继续再次调用len(L) 并每次检查新长度。

    同时解决这两个问题的一个聪明方法是倒数,如Brad Budlong's answer。但这很容易造成栅栏错误。所以,我会用另一种方式来做。

    def rmNegative(L):
        length = len(L)
        i = 0
        while i < length:
            if L[i] < 0:
                del L[i]
                length -= 1
            else:
                i += 1
    

    就是这样。


    如果您想知道为什么您的现有代码是一个无限循环,让我们逐步了解它的作用。

    我们从pos=len(L)-1 开始,所以我们进入大elifpos=pos 什么都不做。如果它是负数,则将其删除并转到新的len(L)-1;如果它是一个正数,你留下它,然后转到len(L)-2。如果它是 0,我们都不做,这意味着 pos=len(L)-1 仍然,我们将永远重复查看那个 0。

    所以,这是获得无限循环的一种方法。但是让我们假设它没有以 0 结尾。

    如果我们刚刚删除了一个负数,我们会返回elif,我们知道这没关系,除非为 0。

    但是如果我们留下一个正数,那么我们现在有pos=len(L)-2,所以我们转到if。同样,pos=pos 什么也不做。如果它是一个正数,我们将列表复制到它自己,它什么都不做,然后设置pos=len(L)-2。这和它已经是一样的了。因此,如果倒数第二个数字是正数,我们将永远关注该数字。这是获得无限循环的另一种方法。

    如果是负数怎么办?然后L[:]=[L[pos]]+L[0:] 将您要删除的值添加到整个列表(其中仍然包括该值的原始副本),L[:]=L[1:] 删除您刚刚添加的值,因此您最终会在L 中得到相同的值开始。然后设置pos=len(L)-1,返回到列表的末尾。我们知道这会成功,然后再次回到倒数第二个插槽,它仍然是相同的值,所以我们将永远来回穿梭。所以,这足以获得无限循环。

    如果它是 0 怎么办?然后我们什么都不做,所以posL 永远不会改变,所以这是获得无限循环的另一种方式。

    因此,一旦我们在列表末尾获得一个正元素,倒数第二个元素的所有三种可能性都是无限循环。

    退一步说,您的代码将pos 设置为的唯一值是len(L)-1len(L)-2。所以,即使你做对了所有其他的事情,这怎么可能在一个超过 2 个非负数的列表上完成?

    【讨论】:

    • 长度减1解决了跑偏的问题,但是你有一个问题,如果你连续有两个负数,你会错过第二个。那是因为您删除了第 i 项并移至第 i+1 项,但删除将下一项向下移动到索引 i 并且您没有检查它。您需要将 i += 1 放入 else 来解决此问题。
    • @BradBudlong:不,我没有。请注意,i += 1 仅出现在 else 中。另请注意,有一整段内容对此进行了解释。
    • 我在评论您的原始版本没有解决和解释问题。
    • @BradBudlong:虽然我确实有一个缩进错误,但我确实修复了一个缩进错误,并且文本中有很多错别字,最糟糕的是,length - 1 而不是length -= 1。无论如何,你的评论才5分钟前,你可以看到8分钟前here的版本,它也已经修复了所有这些。
    【解决方案6】:

    代码:

    def rmNegatives(L):
        i = 0
        while i < len(L):
            if L[i] < 0:
                L.pop(i)
            else:
                i += 1
        return L
    

    【讨论】:

      猜你喜欢
      • 2018-10-22
      • 2022-07-21
      • 2014-01-24
      • 2021-11-28
      • 2021-03-30
      • 2021-07-21
      • 2021-11-13
      • 2013-10-30
      • 1970-01-01
      相关资源
      最近更新 更多