0
    print difflist
    for line in difflist:
        if ((line.startswith('<'))or (line.startswith('>')) or (line.startswith('---'))):
            difflist.remove(line)
    print difflist

在这里,最初,

difflist = ['1a2', '> ', '3c4,5', '< staring', '---', '> starring', '> ', '5c7', '< at ', '---', '> add ', '']

我对代码的期望是打印

['1a2', '3c4,5', '5c7', '']

但我得到的是

difflist= ['1a2', '3c4,5', '---', '> ', '5c7', '---', '']
4

6 回答 6

3

当迭代一个列表时,python 会保留它指向的数组元素的整数索引。但是,当您删除当前元素时,所有后面的元素都会转移到较低的索引。然后位置索引会在您“看到”移动以取代您删除的元素的元素之前递增。

最终,最好通过列表理解来完成:

difflist = [ line for line in difflist if not line.startswith(('<','>','---'))]

如果您真的需要就地执行操作,只需在左侧使用切片分配:

difflist[:] = [ line for line in difflist if not line.startswith(('<','>','---'))]
于 2013-04-17T23:24:36.480 回答
2

我认为您可能会使迭代器无效;换句话说,您不应该尝试删除您正在循环的列表中的项目。

您可能想要创建一个仅包含您关心的项目的新列表。

例如:

newdifflist = []
for line in difflist:
    if not ((line.startswith('<'))or (line.startswith('>')) or (line.startswith('---'))):
        newdifflist.append(line)

更 Pythonic,使用列表推导和多个参数startswith()

newdifflist = [line for line in difflist if not line.startswith(('<', '>', '---')) ]
于 2013-04-17T23:21:36.820 回答
1
result = []
for line in difflist:
    if not line.startswith(('<', '>', '---')):
        result += [line]

或使用列表推导:

[line for line in difflist if not line.startswith(('<', '>', '---'))]
于 2013-04-17T23:24:29.693 回答
1

改为这样做:

>>> difflist = [i for i in difflist if not i.startswith(('<','>','---'))]
>>> difflist
['1a2', '3c4,5', '5c7', '']

这样做.remove()会改变顺序,因此(有点)弄乱了 for 循环。查看 mgilson 的答案以获取更多信息

于 2013-04-17T23:25:09.883 回答
0

而不是试图从列表中删除该项目,让它什么都不做,并用你想要的东西创建另一个列表。

array = []
for line in difflist:
    if ((line.startswith('<'))or (line.startswith('>')) or (line.startswith('---'))):
        pass
    else:
        array.append(line)

现在数组将是您正在寻找的数组!

于 2013-04-17T23:25:25.203 回答
0

发生的事情并没有什么“异常”。事实上,这很正常。这是正在发生的事情:

  1. 循环正在查看项目i
  2. 的项目符合你的测试,所以你删除它。以前的项目i+1现在是项目i
  3. 您的循环再次开始,迭代器前进以指向项目i+1,但项目i从未经过测试。

有几种可能的解决方案:

  1. 制作一个只包含您想要的项目的新列表,而不是从现有列表中删除项目。这具有更好的算法复杂性,并且在 Python 中也更高效,但它可以使用更多的内存。
  2. 以相反的顺序迭代列表。这样,您只需要移动您已经查看过的项目。
  3. 遍历列表的副本。
  4. 使用内部while循环而不是if.

对于这个问题,解决方案 #4 可能如下所示:

for i, line in enumerate(difflist):
    while line.startswith(('<', '>', '---')):
        difflist.pop(i)
        line = difflist[i]

这样,您将一直查看相同的索引,直到它未通过测试,然后才允许迭代器继续进行下一个。

(我冒昧地删除了您条件中过多的不必要的括号,并将您的更改removepop-remove每次都需要从列表的开头进行搜索,使您的循环成为Schlemiel the Painter 的算法)。

您可以研究的另一件事是使用deque(来自collections模块);这是一个链表(普通的 Pythonlist实际上是一个可调整大小的数组),从中删除元素会更快一些。

于 2013-04-17T23:25:57.180 回答