2012-01-29 9 views
6

in Python (2.7) possiamo fare:rimozione di una lista da un altro

>>> a = [1, 2, 3] 
>>> b = [4 , 5] 
>>> a + b 
[1, 2, 3, 4, 5] 

Tuttavia non possiamo fare a - b.

Dal momento che Python sembra avere qualcosa di interessante per quasi tutto, qual è il più pitone per fare a-b, secondo lei?

Domanda simile per dizionari, che non possono né a + b né a -b, dove a e b sono entrambi dizionari. Grazie.

+8

Quale sarebbe il risultato per '[1, 2, 3, 1, 2, 1] - [1, 2]'? – JJJ

+0

@Juhana Domanda brillante. Sarebbe: [3]. – dublintech

+4

Quindi direi perché non '[3, 1, 2, 1]'? –

risposta

11

Si può fare questo con i set:

>>> s = set([1,2,3] + [4,5]) 
>>> s - set([4, 5]) 
{1, 2, 3} 

La differenza principale, naturalmente, è un insieme non può contenere elementi duplicati.

+2

Un 'set' in python non conserva necessariamente l'ordine dei suoi elementi –

+2

' set', sicuramente la cosa migliore da fare – juliomalegria

5

lo farei:

>>> a = [1, 2, 3] 
>>> b = [2, 3] 
>>> filter(lambda x: x not in b, a) 
[1] 

o utilizzando list comprehension

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

e può essere fatto allo stesso modo per i dizionari.

Set ha definito l'operatore - e i metodi difference e symmetric_difference. Se stai pianificando di fare un uso estensivo di tali operazioni usa set invece di list o dict.

+3

Questo è 'O (n * m)' - quindi se la tua lista non contiene elementi duplicati, usa meglio i set e l'operatore '-'. – ThiefMaster

+0

Ovviamente. Ecco perché ho scritto "Se hai intenzione di fare un uso esteso ..." :) –

2

La risposta dipende dalla semantica desiderata di a - b.

Se si desidera solo i primi elementi, quindi affettare è il modo naturale per farlo:

In [11]: a = [1, 2, 3] 

In [12]: b = [4 , 5] 

In [13]: ab = a + b 

In [14]: ab[:len(a)] 
Out[14]: [1, 2, 3] 

Se, d'altra parte, si desidera rimuovere elementi della prima lista non trovato nella seconda lista:

In [15]: [v for v in ab if v not in b] 
Out[15]: [1, 2, 3] 

Il secondo tipo di operazione è naturalmente più espressi utilizzando insiemi:

In [18]: set(ab) - set(b) 
Out[18]: set([1, 2, 3]) 

Nota che generalmente questo non preserva l'ordinamento degli elementi (poiché gli insiemi non sono ordinati). Se ordine è importante, e b rischia di essere lungo, convertendo b in un set può migliorare le prestazioni:

In [19]: bset = set(b) 

In [20]: [v for v in ab if v not in bset] 
Out[20]: [1, 2, 3] 

per i dizionari, esiste già un'operazione "aggiunta" in-place. Si chiama dict.update().

1

y = set(b)
aminusb = filter(lambda p: p not in y,a)

+1

Questo è O (n + m), anche se l'uso di un 'lambda' rende questa soluzione un po 'più lenta –

3

vorrei provare [x for x in a if a not in b].

+1

Questo è' O (n * m) ' –

+0

Questo è corretto, ma è comunque un po 'pacchiano. – phimuemue

+0

pythonesque ?? ... pitonico? – juliomalegria

1

Prova questa:

def list_sub(lst1, lst2): 
    s = set(lst2) 
    return [x for x in lst1 if x not in s] 

list_sub([1, 2, 3, 1, 2, 1, 5], [1, 2]) 
> [3, 5] 

È una soluzione O(n+m) a causa del fatto che si sta usando un precalcolate set, quindi ricerca adesione sarà veloce. Inoltre, manterrà l'ordine degli elementi originali e rimuoverà i duplicati.

0

Order non viene mantenuto, ma ha il risultato desiderato:

>>> def list_diff(a, b): 
...  return list(set(a) - set(b)) 
... 
>>> print list_diff([1, 2, 3, 1, 2, 1], [1, 2]) 
[3] 
0

Qui ci sono le mie opzioni preferite, una comportano l'uso del ciclo for l'altro di conversione per impostare. In caso di piccole dimensioni lista per ciclo è accettabile come si può vedere in una dimensione elenco di 10,

In [65]: d1 = range(10) 

In [66]: d2 = range(1) 

In [67]: %timeit [x for x in d1 if x not in d2] 
1000000 loops, best of 3: 827 ns per loop 

In [68]: %timeit list(set(d1)-set(d2)) 
1000000 loops, best of 3: 1.25 µs per loop 

Tuttavia se la dimensione lista è abbastanza grande, allora probabilmente si dovrebbe utilizzare SET,

In [69]: d1 = range(10000) 

In [70]: d2 = range(1000) 

In [71]: %timeit [x for x in d1 if x not in d2] 
10 loops, best of 3: 105 ms per loop 

In [72]: %timeit list(set(d1)-set(d2)) 
1000 loops, best of 3: 566 µs per loop 
Problemi correlati