我想在列表中找到非唯一元素,但我无法弄清楚为什么下面的代码部分没有发生这种情况。
>>> d = [1, 2, 1, 2, 4, 4, 5, 'a', 'b', 'a', 'b', 'c', 6,'f',3]
>>> for i in d:
... if d.count(i) == 1:
... d.remove(i)
...
>>> d
[1, 2, 1, 2, 4, 4, 'a', 'b', 'a', 'b', 6, 3]
6 和 3 应该被删除。 如果我使用
d = [1, 2, 1, 2, 4, 4, 5, 'a', 'b', 'a', 'b', 'c']
我得到了正确的答案。请解释发生了什么,我很困惑!!!
我正在使用 python 2.7.5。
最佳答案
在遍历列表的同时删除列表中的元素从来都不是一个好主意。执行此操作的适当方法是使用 collections.Counter
用list comprehension :
>>> 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
,而循环它。它看起来像这样:
+-----------------------+ | a | b | b | c | +-----------------------+ ^ (first iteration) +-----------------------+ | a | b | b | c | +-----------------------+ ^ (next iteration: we found a 'b' -- remove it) +-----------------------+ | a | | b | c | +-----------------------+ ^ (removed b) +-----------------+ | a | b | c | +-----------------+ ^ (shift subsequent elements down to fill vacancy) +-----------------+ | a | b | c | +-----------------+ ^ (next iteration)
注意我们跳过了第二个b
!一旦我们删除了第一个 b
,元素就会向下移动,因此我们的 for
循环无法触及列表的每个元素。同样的事情也会发生在您的代码中。
关于python - 在列表中查找非唯一元素不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19006095/