使用while循环从列表Python中删除负数

时间:2015-04-17 05:55:32

标签: python list while-loop negative-number

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

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

6 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

如果您无法承担创建新列表的费用,则必须使用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]

答案 2 :(得分:0)

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

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

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

一次解决这两个问题的一个聪明方法是向后计数,如Brad Budlong's answer。但这可以很容易地制造出fencepost错误。所以,我会以另一种方式做到这一点。

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个非负数的列表上完成呢?

答案 3 :(得分:0)

代码:

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

答案 4 :(得分:-1)

以下是我rmNegative(L)的实现。

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

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

答案 5 :(得分:-2)

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

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