2013-08-12 36 views
5

Sto cercando di rimuovere i duplicati da 2 liste. così ho scritto questa funzione:python rimuovere i duplicati da 2 liste

a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 

b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 

for i in b: 
    if i in a: 
     print "found " + i 
     b.remove(i) 

print b 

Ma trovo che gli elementi corrispondenti che seguono un articolo abbinato non vengono rimossi.

ottengo risultato come questo:

found ijk 
found opq 
['lmn', 'rst', '123', '456'] 

ma mi aspetto risultato come questo:

[ '123', '456']

Come posso risolvere la mia funzione di fare ciò Voglio?

Grazie.

+0

I ti ha dato una soluzione che mantiene entrambe le tue liste, nello stesso ordine e rimuove i duplicati in ciascuno di essi. Immagino che questo sia quello che stavi cercando. –

risposta

9

Il tuo problema sembra essere che stai cambiando la lista su cui stai iterando. Alterna invece una copia dell'elenco.

for i in b[:]: 
    if i in a: 
     b.remove(i) 


>>> b 
['123', '456'] 

Tuttavia, che ne dite di utilizzare una comprensione di lista?

>>> a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 
>>> b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 
>>> [elem for elem in b if elem not in a ] 
['123', '456'] 
+0

Se la lista 'a' cresce più a lungo può risultare che trasformarla in un' set' è molto più efficiente ('x in s' è O (1) per i set, O (n) per gli elenchi) secondo http : //wiki.python.org/moin/TimeComplexity –

+0

@Downvoter: puoi lasciare un commento su cosa c'è di sbagliato in questa risposta? Mi piacerebbe davvero migliorarlo. :) –

+0

Per la cronaca, non ho fatto downvot. :-) –

1

o un set

set(b).difference(a) 

essere avvertiti set non preserverà ordine se questo è importante

7

Che dire

b= set(b) - set(a) 

Se avete bisogno di possibili ripetizioni in b a anche appaiono ripetuti nel risultato e/o nell'ordine da conservare, quindi

b= [ x for x in b if not x in a ] 

farebbe.

+1

Questa risposta è stata downvoted una volta. Qualcuno può dire perché? Qualunque sintassi grave/errore concettuale? Non contribuire alla domanda posta (e considerando che a volte è estremamente difficile capire cosa viene chiesto)? Cattivo inglese fino al punto di incomprensibilità? –

2

ti ha chiesto di rimuovere entrambe le liste duplica, ecco la mia soluzione:

from collections import OrderedDict 
a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 
b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 

x = OrderedDict.fromkeys(a) 
y = OrderedDict.fromkeys(b) 

for k in x: 
    if k in y: 
     x.pop(k) 
     y.pop(k) 


print x.keys() 
print y.keys() 

Risultato:

['abc', 'def', 'xyz'] 
['123', '456'] 

La cosa bella è che si mantiene l'ordine di entrambi gli elementi liste

18

Ecco cosa sta succedendo. Supponiamo di avere questo elenco:

['a', 'b', 'c', 'd'] 

e si sta eseguendo il ciclo su ogni elemento nell'elenco. Supponiamo che tu sia attualmente nella posizione indice 1:

['a', 'b', 'c', 'd'] 
    ^
     | 
    index = 1 

...e si rimuove l'elemento in posizione di indice 1, dando in questo modo:

['a',  'c', 'd'] 
    ^
     | 
    index 1 

Dopo aver rimosso la voce, gli altri oggetti di scorrimento verso sinistra, dando in questo modo:

['a', 'c', 'd'] 
    ^
     | 
    index 1 

poi, quando il ciclo viene eseguito ancora una volta, il ciclo incrementa l'indice a 2, dando in questo modo:

['a', 'c', 'd'] 
      ^
      | 
     index = 2 

vedere come si saltato 'c'? La lezione è: non eliminare mai un elemento da una lista in loop.

+4

Questa risposta contiene una spiegazione perfettamente chiara della causa del problema, non capisco perché ha ottenuto un voto negativo. – Bart

+0

Sì, hai ragione. Si spera che sia un errore che non può essere corretto perché i downvote sono bloccati una volta dati. –

+0

Forse il motivo dei downvotes è l'assenza di una soluzione di lavoro ... –

1

Un modo per evitare il problema della modifica di una lista, mentre si scorrere su di esso, è quello di utilizzare comprensioni:

a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 
b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 
b = [x for x in b if not x in a] 
+0

La stessa soluzione pubblicata 1 ora fa da Mario Rossi e Sukrit Kalra. –

+0

Forse @ Mayur Patel ha iniziato a scriverlo nello stesso momento di me. Questo è un argomento per meta (credo): o bloccando domande quando 1 (o forse 2) persone stanno rispondendo a loro (per un certo periodo di tempo?), O almeno un'indicazione di quante altre persone stanno rispondendo. Voglio dire prima che le risposte siano ** pubblicate **. Io sono un noobie, però. Se qualcosa del genere è già lì, per favore fatemelo sapere. –

0

Ci sono già molte risposte su "come si può risolvere il problema?", Quindi questo è un "come si può migliorare e essere più divinatorio?": poiché ciò che si vuole raggiungere è quello di ottenere la differenza tra lista b e la lista a, si dovrebbe usare il funzionamento differenza sul set (operations on sets):

>>> a = ["abc", "def", "ijk", "lmn", "opq", "rst", "xyz"] 
>>> b = ["ijk", "lmn", "opq", "rst", "123", "456", ] 
>>> s1 = set(a) 
>>> s2 = set(b) 
>>> s2 - s1 
set(['123', '456']) 
Problemi correlati