3

我不允许使用 .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 不返回

4

3 回答 3

2

那是因为您正在遍历列表并同时对其进行修改。这意味着索引i并不总是正确的,因为您刚刚从列表中删除了一个元素。这会导致跳过元素,这就是为什么1不在那里。

你可以做:

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

这使用列表推导来创建一个没有偶数的列表。如果您需要修改现有列表,您可以执行以下操作:

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来跟踪需要删除的元素的位置。

于 2013-11-08T00:21:15.903 回答
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这是另一种只用/xrange和做同样事情的方法len

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

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

于 2013-11-08T00:31:49.067 回答
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]

或者

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

或者

>>> 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]
于 2013-11-08T00:24:18.653 回答