[英]finding non-unique elements in list not working
I wanted to find the non-unique elements in the list, but I am not able to figure out why this is not happening in the below code section.我想在列表中找到非唯一元素,但我无法弄清楚为什么下面的代码部分没有发生这种情况。
>>> 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 and 3 should have been removed. 6 和 3 应该已被删除。 where as, if I use
在哪里,如果我使用
d = [1, 2, 1, 2, 4, 4, 5, 'a', 'b', 'a', 'b', 'c']
I am getting correct answer.我得到了正确的答案。 Please explain what is happening, I am confused !!!
请解释发生了什么,我很困惑!
I am using python 2.7.5.我正在使用 python 2.7.5。
Removing elements of a list while iterating over it is never a good idea.在迭代列表时删除列表的元素从来都不是一个好主意。 The appropriate way to do this would be to use a
collections.Counter
with a list comprehension :执行此操作的适当方法是使用带有列表理解的
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]
If you want keep the duplicate elements in the order in which they appear in your list:如果您想按照它们在列表中出现的顺序保留重复元素:
>>> 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']
I'll try to explain why your approach doesn't work.我会试着解释为什么你的方法不起作用。 To understand why some elements aren't removed as they should be, imagine that we want to remove all
b
s from the list [a, b, b, c]
while looping over it.要理解为什么某些元素没有按原样删除,请想象我们要在循环遍历列表
[a, b, b, c]
时从列表中删除所有b
。 It'll look something like this:它看起来像这样:
+-----------------------+ | 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)
Notice that we skipped the second b
!请注意,我们跳过了第二个
b
! Once we removed the first b
, elements were shifted down and our for
-loop consequently failed to touch every element of the list.一旦我们删除了第一个
b
,元素就会向下移动,我们的for
循环因此无法触及列表中的每个元素。 The same thing happens in your code.同样的事情发生在你的代码中。
Better use collections.Counter() :更好地使用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]
Also see relevant thread:另请参阅相关线程:
I just thought I would add my method with set comprehension if anyone was interested.我只是想如果有人感兴趣,我会用集合理解添加我的方法。
>>> 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 and up I believe for the set comprehension functionality.我相信 Python 2.7 及更高版本的集合理解功能。
Thanks for all the answers and comments !感谢所有的回答和评论!
Thought for a while and got another answer in my previous way I have written the code.想了一会儿,得到了另一个答案,以我以前编写代码的方式。 So, I am posting it.
所以,我发布它。
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, Your explanation led me to this trick. @arshajii,你的解释让我想到了这个技巧。 Thanks !
谢谢!
You can also do like this :你也可以这样做:
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] [1, 2, 3, 1, 2, 3, 1, 2, 1]
For对于
>>> d = [1, 2, 1, 2, 4, 4, 5, 'a', 'b', 'a', 'b', 'c', 6,'f',3]
Using conversion to a set yields the unique items:使用转换为集合会产生唯一项:
>>> d_unique = list(set(d))
Non-unique items can be found using a list comprehension可以使用列表理解找到非唯一项
>>> [item for item in d_unique if d.count(item) >1]
[1, 2, 4, 'a', 'b']
In python3, use dict.items()
instead of dict.iteritems()
在 python3 中,使用
dict.items()
代替dict.iteritems()
iteritems()
was removed in python3, so you can't use this method anymore. iteritems()
在 python3 中被删除,所以你不能再使用这个方法了。
>>> 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).items() if v > 1]
['a', 1, 2, 'b', 4]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.