在迭代列表时删除其元素从未是一个好的想法。正确的做法是使用 collections.Counter
与 列表推导式:
>>> from collections import Counter
>>> d = [1, 2, 1, 2, 4, 4, 5, 'a', 'b', 'a', 'b', 'c', 6, 'f', 3]
>>> # Use items() instead of iteritems() in Python 3
>>> [k for (k,v) in Counter(d).iteritems() if v > 1]
['a', 1, 2, 'b', 4]
如果你希望保留列表中出现的重复元素的顺序:
>>> keep = {k for (k,v) in Counter(d).iteritems() if v > 1}
>>> [x for x in d if x in keep]
[1, 2, 1, 2, 4, 4, 'a', 'b', 'a', 'b']
我会尝试解释为什么你的方法不起作用。为了理解某些元素未按预期删除的原因,想象一下我们要在循环列表[a,b,b,c]
时删除所有的b
s。它看起来像这样:
+-----------------------+
| a | b | b | c |
+-----------------------+
^(第一次迭代)
+-----------------------+
| a | b | b | c |
+-----------------------+
^(下一个迭代:我们找到了一个“b”--删除它)
+-----------------------+
| a | | b | c |
+-----------------------+
^(已删除b)
+-----------------+
| a | b | c |
+-----------------+
^(将随后的元素向下移动以填补空缺)
+-----------------+
| a | b | c |
+-----------------+
^(下一个迭代)
注意,我们跳过了第二个b
!一旦我们删除了第一个b
,元素就被向下移动,我们的for
循环因此未能触及列表的每个元素。在您的代码中发生了同样的事情。
items()
替换了iteritems()
,这样对我来说很好用。请注意,这不会改变原意。 - gplssm