2013-02-28 23 views
14

Mam dwie listy powiedziećJak sprawdzić, czy wszystkie pozycje na liście znajdują się na innej liście?

List1 = ['a','c','c'] 
List2 = ['x','b','a','x','c','y','c'] 

Teraz chcę się dowiedzieć, czy są tam wszystkie elementy List1 w lista2. W tym przypadku wszystko jest. Nie mogę użyć funkcji podzbioru, ponieważ mogę powtarzać elementy na listach. Mogę użyć pętli for, aby zliczyć liczbę wystąpień każdego elementu na Liście 1 i sprawdzić, czy jest on mniejszy lub równy liczbie wystąpień na Liście2. Czy jest lepszy sposób to zrobić?

Dzięki.

Odpowiedz

25

Nadal można korzystać z funkcji podzbioru, tworząc zestaw na bieżąco:

>>> list1 = ['a', 'c', 'c'] 
>>> list2 = ['x', 'b', 'a', 'x', 'c', 'y', 'c'] 
>>> set(list1) < set(list2) 
True 

Lub jeśli chcesz sprawdzić, czy liczba wystąpień pasuje, można skorzystać z rodzaju licznika i określenia własny podzbiór relacja:

>>> from collections import Counter 
>>> def counterSubset(list1, list2): 
     c1, c2 = Counter(list1), Counter(list2) 
     for k, n in c1.items(): 
      if n > c2[k]: 
       return False 
     return True 

>>> counterSubset(list1, list2) 
True 
>>> counterSubset(list1 + ['a'], list2) 
False 
>>> counterSubset(list1 + ['z'], list2) 
False 

Jeśli masz już liczniki (co może być użyteczną alternatywę do przechowywania danych i tak), można też po prostu napisać to jako pojedyncza linia:

>>> all(n <= c2[k] for k, n in c1.items()) 
True 
+0

Witam, druga część jest tym, co próbowałem zrobić. Wygląda na to, że to jedyna droga. Dzięki! – pogo

+0

Czy zawiedzie w przypadku "[" s "," e "," r "," "," "," "," y "]" i "[" "," "," "," y " ] ' – SIslam

+0

@SIslam Zależy od zamówienia. Druga lista jest podzbiorem poprzedniej listy, więc rozwiązanie w mojej odpowiedzi poprawnie ją rozpozna. – poke

0

Spowoduje to powrót prawda to wszystkie elementy listy1 są w lista2

def list1InList2(list1, list2): 
    for item in list1: 
     if item not in list2: 
      return False 
    return True 
+1

Nie jestem downvoter, ale powinieneś naprawdę rzucić okiem na [PEP 8] (http://www.python.org/dev/peps/pep-0008/). Twoja składnia 'if' jest wyłączona, masz niepotrzebny średnik, a twój styl nazywania zmiennych powinien być zarezerwowany dla klas. –

+1

Można to również zredukować do pojedynczej linii: 'all (pozycja na liście2 dla pozycji na liście1)'. –

+0

Użyłem List1 i List2 jako nazw zmiennych, ponieważ to właśnie było w pytaniu i minęło trochę czasu odkąd użyłem Pythona, więc przyjmuję średniki i nawiasy wokoło jeśli były moje złe – jeffam217

1
def check_subset(list1, list2): 
    try: 
     [list2.remove(x) for x in list1] 
     return 'all elements in list1 are in list2' 
    except: 
     return 'some elements in list1 are not in list2' 
2

zdawać sobie sprawę z następujących powodów:

>>>listA = ['a', 'a', 'b','b','b','c'] 
>>>listB = ['b', 'a','a','b','c','d'] 
>>>all(item in listB for item in listA) 
True 

Jeśli czytasz „wszystkie” linię jak ty w języku angielskim, to nie jest złe, ale może wprowadzać w błąd, ponieważ listA ma trzecie "b", ale lista B nie.

Ma to również ten sam problem:

def list1InList2(list1, list2): 
    for item in list1: 
     if item not in list2: 
      return False 
    return True 

Tylko uwaga. Następujące funkcje nie działają:

>>>tupA = (1,2,3,4,5,6,7,8,9) 
>>>tupB = (1,2,3,4,5,6,6,7,8,9) 
>>>set(tupA) < set(TupB) 
False 

Konwersja krotek do list nadal nie działa. Nie wiem, dlaczego struny działają, ale int nie.

działa, ale ma ten sam problem nie utrzymując liczbę wystąpień elementu:

>>>set(tupA).issubset(set(tupB)) 
True 

Korzystanie z zestawów nie jest kompleksowe rozwiązanie dla multi-occurrance element pasujący.

Ale tu jest rozwiązanie jednego-liner/adaptacja do odpowiedzi shantanoo bez try/z wyjątkiem:

all(True if sequenceA.count(item) <= sequenceB.count(item) else False for item in sequenceA) 

wbudowaną funkcję zawijania listowych używając potrójny operatora warunkowego. Python jest niesamowity! Zauważ, że "< =" nie powinno być "==".

W tym rozwiązaniu sekwencje A i B mogą być krotkami typu tuple i list oraz innymi "sekwencjami" metodami "count". Elementy w obu sekwencjach mogą być większością typów. Nie używałbym tego z dyktami, tak jak jest teraz, stąd użycie "sekwencji" zamiast "iterable".

Powiązane problemy