2012-01-29 11 views
6

w Pythonie (2.7) możemy zrobić:Usunięcie jednej listy z innego

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

Jednak nie możemy zrobić - B.

Ponieważ pyton wydaje się mieć coś fajnego dla prawie wszystkiego, co jest najbardziej python-esque do zrobienia a - b, według ciebie?

Podobne pytanie dla słowników, które nie mogą ani a + b, ani a - b, gdzie aib są słownikami. Dzięki.

+8

Jaki byłby wynik dla '[1, 2, 3, 1, 2, 1] - [1, 2]'? – JJJ

+0

@Juhana Brilliant pytanie. Byłoby: [3]. – dublintech

+4

Wtedy powiedziałbym, dlaczego nie "[3, 1, 2, 1]"? –

Odpowiedz

11

Można to zrobić z zestawów:

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

Główną różnicą jest oczywiście zestaw nie może zawierać zduplikowanych elementów.

+2

"Zestaw" w python niekoniecznie zachowuje kolejność jego elementów –

+2

'zestaw', zdecydowanie najlepsza rzecz do zrobienia – juliomalegria

5

zrobiłbym:

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

lub użyć wyrażeń listowych

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

I można to zrobić w ten sam sposób do słowników.

Set ma zdefiniowany operator - i metody difference i symmetric_difference. Jeśli planujesz szerokie wykorzystanie tych operacji, użyj zestawu zamiast listy lub dyktatu.

+3

To jest' O (n * m) '- więc jeśli twoja lista nie zawiera żadnych duplikatów, lepiej wykorzystaj zestawy i operatora '-'. – ThiefMaster

+0

Oczywiście. Dlatego napisałem "Jeśli planujesz zrobić duży użytek ..." :) –

2

Odpowiedź zależy od pożądanej semantyki a - b.

Jeśli chcesz tylko pierwsze elementy, a następnie krojenie jest naturalnym sposobem, aby to zrobić:

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] 

Jeśli, z drugiej strony, że chcesz usunąć elementy pierwszej liście nie znalazł się w sekundę listy:

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

drugi rodzaj działania jest bardziej naturalnie wyrażane przy użyciu zestawów:

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

Należy zauważyć, że ogólnie nie zachowuje to kolejności elementów (ponieważ zestawy są nieuporządkowane). Jeżeli zamawiający jest ważne, a b prawdopodobnie będzie długa, konwersja b do zestawu może poprawić wydajność:

In [19]: bset = set(b) 

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

słowników istnieje już jest „dodatkiem” działanie w miejscu. Nazywa się dict.update().

1

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

+1

To O (n + m), aczkolwiek używając 'lambda' czyni to rozwiązanie nieco wolniejszym –

3

chciałbym spróbować [x for x in a if a not in b].

+1

To jest' O (n * m) ' –

+0

Zgadza się, ale mimo to jest nieco pythoneque. – phimuemue

+0

pythonesque? ... pytonowo? – juliomalegria

1

Spróbuj tego:

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] 

Jest to rozwiązanie O(n+m) ze względu na fakt, że to za pomocą precomputed set, więc przynależność wyszukiwanie będzie szybkie. Ponadto zachowa kolejność oryginalnych elementów i usunie duplikaty.

0

Zamówienie nie jest zachowana, ale ma wynik chcesz:

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

Oto moje preferowane opcje, jedna wiąże się z wykorzystaniem pętli drugiej konwersji ustawić. W przypadku małych rozmiarów listy pętli for jest do zaakceptowania, jak widać dla rozmiaru lista 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 

Jednak jeśli wielkość lista jest wystarczająco duża, to należy prawdopodobnie użyć ustawiony

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 
Powiązane problemy