从具有del函数的列表中删除evens

时间:2013-11-08 00:18:11

标签: python list for-loop del

我不允许使用.remove()函数来删除列表中的偶数,并且规范说:您将修改原始列表,因此其id()不得更改。这就是我所拥有的:

def remove_evens(xs):
    for i in range(len(xs)):
        for x in xs:
            if x%2==0:
                del xs[i]
    return xs

例如,如果我测试函数并输入xs = [1,2,3,4,5],则返回[3,5]。我不知道1为什么不回来

3 个答案:

答案 0 :(得分:2)

那是因为你在列表上进行迭代并同时修改它。这意味着索引i并不总是正确的,因为您刚刚从列表中删除了一个元素。这导致跳过元素,这就是1不存在的原因。

你可以这样做:

def remove_evens(xs):
    return [x for x in xs if x % 2 != 0]

这使用list comprehension创建没有偶数的列表。如果您需要修改现有列表,您可以这样做:

def remove_evens(xs):
    to_remove = []
    for i, x in enumerate(xs):
        if x % 2 == 0:
            to_remove.append(i)
    for j in to_remove:
        del xs[j]
    return xs

这会创建一个列表to_remove,用于跟踪需要删除的元素的位置。

答案 1 :(得分:2)

也许这样的事情对你有用。

>>> xs = [1,5,123,6,2,34]
>>> id(xs)
35519496L
>>> lastidx = len(xs) - 1
>>> for i, x in enumerate(reversed(xs)):
...     if x%2==0:
...         del xs[lastidx-i]
...
>>> xs
[1, 5, 123]
>>> id(xs)
35519496L

这是线性时间,因为它只在列表上迭代一次。当您向后遍历列表时,您可以自由删除元素,而无需修改尚未循环的未来元素的索引。您也可以看到,此方法的列表ID不会改变。 :)

以下是另一种仅使用range / xrangelen执行相同操作的方法。

>>> xs = [1,5,123,6,2,34]
>>> for i in range(len(xs)-1,-1,-1):
...     if xs[i]%2==0:
...         del xs[i]
...
>>> xs
[1, 5, 123]

两种方式都做同样的事情,无论你决定使用哪种方式都是偏好/个人风格。

答案 2 :(得分:0)

当您在列表上进行迭代时,从列表中删除项目是个坏主意。

您可以通过以下几种方式实现目标:

>>> def deleteEvens(L):
...   dels = []
...   for i,x in enumerate(L):
...     if not x%2:
...       dels.append(i)
...   for d in dels[::-1]:
...     L.pop(d)
... 
>>> L
[1, 2, 3, 4, 5]
>>> deleteEvens(L)
>>> L
[1, 3, 5]

OR

>>> L = [1,2,3,4,5]
>>> odds = [i for i in L if i%2]
>>> odds
[1, 3, 5]

OR

>>> def delEvens(L):
...   dels = []
...   for i,x in enumerate(L):
...     if not x%2:
...       dels.append(i)
...   for d in dels[::-1]:
...     del L[d]
... 
>>> L = [1,2,3,4,5]
>>> delEvens(L)
>>> L
[1, 3, 5]