2013-09-25 117 views
3

我想找到列表中的非唯一元素,但我無法弄清楚爲什麼這不會發生在下面的代碼部分。在列表中找不到非唯一元素不起作用

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

回答

17

在迭代列表時刪除列表中的元素絕不是一個好主意。適當的方式做,這是使用一個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'] 

我會盡力解釋你的方法不起作用的原因。爲了理解爲什麼某些元素不應該被刪除,想象一下,我們希望從列表[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 -loop因此未能觸及列表中的每個元素。同樣的事情發生在你的代碼中。

+0

感謝。使用計數器它正在工作,但爲什麼這段代碼不起作用。我想知道它有什麼問題?! –

+0

@tanmay查看修改。 – arshajii

+0

@arshajii很好的解釋! – alecxe

0

我只是想我要補充我的方法用一套理解,如果有人有興趣。

>>> 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及以上我相信集合理解功能。

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,你的解釋讓我想到了這個把戲。謝謝 !

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]