查找列表中的非唯一元素不起作用

时间:2013-09-25 13:19:22

标签: python python-2.7

我想在列表中找到非唯一元素,但我无法弄清楚为什么在下面的代码部分中没有发生这种情况。

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

6 个答案:

答案 0 :(得分:20)

在迭代列表中删除元素时,这绝不是一个好主意。执行此操作的适当方法是使用collections.Counterlist 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']

我会尝试解释为什么你的方法不起作用。要理解为什么某些元素不会被删除,请想象我们要在循环遍历列表b时删除所有[a, b, b, c]。它看起来像这样:

+-----------------------+
|  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 - 循环因此无法触及列表中的每个元素。你的代码也会发生同样的事情。

答案 1 :(得分:2)

更好地使用collections.Counter()

>>> d = [1, 2, 1, 2, 4, 4, 5, 'a', 'b', 'a', 'b', 'c', 6,'f',3]
>>> from collections import Counter
>>> [k for k, v in Counter(d).iteritems() if v > 1]
['a', 1, 2, 'b', 4]

另见相关主题:

答案 2 :(得分:1)

我只是觉得如果有兴趣的话,我会用set comprehension添加我的方法。

>>> d = [1, 2, 1, 2, 4, 4, 5, 'a', 'b', 'a', 'b', 'c', 6,'f',3]
>>> d = list({x for x in d if d.count(x) > 1})
>>> print d
['a', 1, 2, 'b', 4]

Python 2.7及以上我相信设置理解功能。

答案 3 :(得分:0)

感谢所有的答案和评论!

想了一会儿,我以前的方式得到了另一个答案,我写了代码。所以,我发布了它。

d = [1, 2, 1, 2, 4, 4, 5, 'a', 'b', 'a', 'b', 'c', 6,'f',3]
e = d[:] # just a bit of trick/spice
>>> for i in d:
...     if d.count(i) == 1:
...             e.remove(i)
... 
>>> e
[1, 2, 1, 2, 4, 4, 'a', 'b', 'a', 'b']

@arshajii,你的解释让我想到了这个伎俩。谢谢!

答案 4 :(得分:0)

你也可以这样做:

data=[1,2,3,4,1,2,3,1,2,1,5,6]
    first_list=[]
    second_list=[]
    for i in data:
        if data.count(i)==1:
            first_list.append(i)
        else:
            second_list.append(i)
            print (second_list)

结果

[1,2,3,1,2,3,1,2,1]

答案 5 :(得分:0)

为了

>>> d = [1, 2, 1, 2, 4, 4, 5, 'a', 'b', 'a', 'b', 'c', 6,'f',3]

使用到集合的转换产生唯一项:

>>> d_unique = list(set(d))

可以使用列表推导找到非唯一项

>>> [item for item in d_unique if d.count(item) >1]
[1, 2, 4, 'a', 'b']