2010-10-14 22 views
53

Uważam, że nie jest związany pytanie, o tym, jak znaleźć, jeśli co najmniej jeden element występuje na liście:
How to check if one of the following items is in a list?Jak sprawdzić, czy wszystkie poniższe pozycje znajdują się na liście?

Ale to, co jest najlepsze i pythonic sposobem na znalezienie tego, czy wszystkie elementy istnieje w liście?

Przeszukiwanie docs Znalazłem rozwiązanie:

>>> l = ['a', 'b', 'c'] 
>>> set(['a', 'b']) <= set(l) 
True 
>>> set(['a', 'x']) <= set(l) 
False 

Inne rozwiązanie byłoby to:

>>> l = ['a', 'b', 'c'] 
>>> all(x in l for x in ['a', 'b']) 
True 
>>> all(x in l for x in ['a', 'x']) 
False 

Ale tu trzeba zrobić więcej pisać.

Czy istnieją inne rozwiązania?

+4

Co jest nie tak z 'zestawem (mniejszym) <= zestawem (większym)'? – eumiro

Odpowiedz

42

Operatory takie jak <= w języku Python na ogół nie są zastępowane, aby oznaczać coś znacznie innego niż "mniej niż lub równe ". To niecodzienne, że robi to standardowa biblioteka - dla mnie pachnie jak starsze API.

Użyj równoważnej i bardziej przejrzystej metody, set.issubset. Zauważ, że nie musisz konwertować argumentu na zestaw; zrobi to dla ciebie w razie potrzeby.

set(['a', 'b']).issubset(['a', 'b', 'c']) 
+2

nie wiedziałem, że możesz przekazać listę bezpośrednio jako argument do issubset ... fajnie! – tsimbalar

+0

Chociaż zgadzam się z sentymentem, jestem całkiem w porządku z ideą '<=' i 'issubset', co oznacza to samo. Dlaczego ci się nie podoba? –

+2

@Just: Przede wszystkim dlatego, że nie jest oczywiste, co '<=' oznacza dla zestawu bez szukania go w dokumentach lub z wcześniejszą wiedzą o tym, co to znaczy w teorii zbiorów, podczas gdy każdy wie, co 'issubset' oznacza automatycznie. –

49

I prawdopodobnie używać set w następujący sposób:

set(l).issuperset(set(['a','b'])) 

lub na odwrót:

set(['a','b']).issubset(set(l)) 

uważam, że nieco bardziej czytelne, ale może to być ponad-kill. Zestawy są szczególnie przydatne do obliczania związku/przecięcia/różnic między kolekcjami, ale może nie być najlepszą opcją w tej sytuacji ...

+0

W rzeczywistości 'MySet.issubset (MyOtherSet)' i 'MySet <= MyOtherSet' są takie same. – Wok

+1

@wok: oh Nie wiedziałem o tym, ale myślę, że składnia <= jest nieco myląca, ponieważ podobną składnię można stosować z listami, ale z zupełnie innym znaczeniem. – tsimbalar

+2

Nie jest to takie mylące, jeśli pamiętasz, że włączenie definiuje częściową kolejność na dowolnym zestawie zestawów.W rzeczywistości trochę mylące jest to, że '<=' ma znaczenie dla sekwencji: można by się spodziewać, że będzie to "podciąg" zamiast uporządkowania leksykograficznego. – aaronasterling

4

Lubię te dwa, ponieważ wydają najbardziej logiczne, przy czym ten ostatni krótsza i prawdopodobnie najszybszy (pokazane tutaj za pomocą nowego zestawu literałów które były backported do Python 2.7):

all(x in {'a', 'b', 'c'} for x in ['a', 'b']) 
# or 
{'a', 'b'}.issubset({'a', 'b', 'c'}) 
1

Co zrobić, jeśli listy zawierają takie duplikaty:

v1 = ['s', 'h', 'e', 'e', 'p'] 
v2 = ['s', 's', 'h'] 

Zestawy nie zawierają duplikatów. Tak więc poniższy wiersz zwraca True.

set(v2).issubset(v1) 

Aby liczyć duplikatów, można użyć kodu:

v1 = sorted(v1) 
v2 = sorted(v2) 


def is_subseq(v2, v1): 
    """Check whether v2 is a subsequence of v1.""" 
    it = iter(v1) 
    return all(c in it for c in v2) 

więc następujący wiersz zwraca False.

is_subseq(v2, v1) 
Powiązane problemy