6

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

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

4

6 回答 6

25

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

我将尝试解释为什么您的方法不起作用。要了解为什么某些元素没有按应有的方式删除,假设我们想在循环遍历列表时b从列表中删除所有 s 。[a, b, b, c]它看起来像这样:

+------------------------+
| 一个 | 乙 | 乙 | c |
+------------------------+
   ^(第一次迭代)

+------------------------+
| 一个 | 乙 | 乙 | c |
+------------------------+
         ^(下一次迭代:我们找到了一个“b”——删除它)

+------------------------+
| 一个 | | 乙 | c |
+------------------------+
         ^(删除 b)

+-----------------+
| 一个 | 乙 | c |
+-----------------+
         ^(将后续元素向下移动以填补空缺)

+-----------------+
| 一个 | 乙 | c |
+-----------------+
               ^(下一次迭代)

请注意,我们跳过了第二个b!一旦我们删除了第一个b,元素就会向下移动,for因此我们的 -loop 无法触及列表的每个元素。同样的事情也发生在您的代码中。

于 2013-09-25T13:25:03.763 回答
4

更好地使用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]

另请参阅相关线程:

于 2013-09-25T13:25:49.313 回答
2

我只是想如果有人感兴趣,我会在我的方法中添加集合理解。

>>> 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 及更高版本我相信集合理解功能。

于 2013-09-25T13:37:35.160 回答
1

感谢所有的答案和评论!

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

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,您的解释使我想到了这个技巧。谢谢 !

于 2013-09-25T14:27:35.957 回答
1

你也可以这样做:

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]

于 2016-09-21T06:56:29.050 回答
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']
于 2021-01-14T14:20:50.860 回答