Wie überprüfe ich, ob alle folgenden Elemente in einer Liste enthalten sind?


113

Ich habe festgestellt, dass es eine verwandte Frage gibt, wie man herausfindet, ob mindestens ein Element in einer Liste vorhanden ist:
Wie kann man überprüfen, ob eines der folgenden Elemente in einer Liste enthalten ist?

Aber wie lässt sich am besten und pythonisch feststellen, ob alle Elemente in einer Liste vorhanden sind?

Beim Durchsuchen der Dokumente habe ich folgende Lösung gefunden:

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

Eine andere Lösung wäre:

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

Aber hier müssen Sie mehr tippen.

Gibt es noch andere Lösungen?


5
Was ist los mit set(smaller) <= set(larger)?
Eumiro

1
Ich denke, Ihre zweite Lösung mit 'all' sieht für mich gut und pythonisch aus.
Jiho Noh

Antworten:


155

Operatoren wie <=in Python werden im Allgemeinen nicht überschrieben, um etwas signifikant anderes als "kleiner als oder gleich" zu bedeuten. Es ist ungewöhnlich, dass die Standardbibliothek dies tut - es riecht für mich nach Legacy-API.

Verwenden Sie die entsprechende und klarere Methode set.issubset. Beachten Sie, dass Sie das Argument nicht in eine Menge konvertieren müssen. Das erledigt es bei Bedarf für Sie.

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

2
Ich wusste nicht, dass Sie die Liste direkt als Argument an issubset übergeben können ... nett!
Tsimbalar

1
Obwohl ich dem Gefühl zustimme, bin ich mit der Idee <=und issubsetBedeutung derselben Sache ziemlich einverstanden . Warum magst du es nicht?
Kirk Strauser

2
@Just: In erster Linie, weil es nicht offensichtlich ist, was <=für ein Set bedeutet, ohne es entweder in den Dokumenten nachzuschlagen oder vorher zu wissen, was es in der Set-Theorie bedeutet, während jeder weiß, was issubsetautomatisch bedeutet.
Glenn Maynard

2
Sie kennen den mathematischen Operator für (nicht richtige) Teilmenge? es sieht im Grunde ziemlich nach einem gerundeten <=;) aus
dom0

liebe diese Lösung. Gibt es eine Möglichkeit, einen Indexspeicherort oder einen Listenwert anstelle eines Bools (True: False) abzurufen?
Vlad Gulin

62

Ich würde wahrscheinlich setauf folgende Weise verwenden:

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

oder umgekehrt:

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

Ich finde es etwas lesbarer, aber es kann übertrieben sein. Mengen sind besonders nützlich, um Vereinigung / Schnittmenge / Unterschiede zwischen Sammlungen zu berechnen, aber in dieser Situation ist dies möglicherweise nicht die beste Option ...


Eigentlich MySet.issubset(MyOtherSet)und MySet <= MyOtherSetsind gleich.
Wok

1
@wok: Oh, das wusste ich nicht, aber ich denke, die <= -Syntax ist etwas verwirrend, da eine ähnliche Syntax mit Listen verwendet werden kann, aber mit einer ganz anderen Bedeutung.
Tsimbalar

3
Es ist nicht wirklich verwirrend, wenn Sie sich daran erinnern, dass die Aufnahme eine Teilreihenfolge für einen Satz von Sätzen definiert. Es ist tatsächlich etwas verwirrend, <=was die Bedeutung hat, die es für Sequenzen hat: Man könnte erwarten, dass es eher eine Teilsequenz als eine lexikografische Reihenfolge bedeutet.
Aaronasterling

1
@aaronasterling: mmm, ich persönlich denke nicht zu viel über "Teilreihenfolge" nach, wenn ich Code eingebe :-), aber ich stimme der Tatsache zu, dass sich die Verwendung <=mit Sequenzen irgendwie auch seltsam anfühlt ...
tsimbalar

3
Ich lief in einen kleinen gotcha hier möchte ich erwähnen: Wenn Sie diese Methode verwenden, Sie werden Ihre Listen zu Sätzen Umwandlung, die keine Duplikate bedeuten. set(['a','a']).issubset(['a'])kehrt zurück True.
Orangestar

11

Ich mag diese beiden, weil sie am logischsten erscheinen, wobei letztere kürzer und wahrscheinlich am schnellsten sind (hier mit setwörtlicher Syntax gezeigt, die auf Python 2.7 zurückportiert wurde ):

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

Die "all" -Lösung ist am schnellsten, wenn Sie sie mit timeit () messen. Dies sollte die akzeptierte Antwort sein.
Attersson

3

Was ist, wenn Ihre Listen Duplikate wie diese enthalten:

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

Sets enthalten keine Duplikate. Die folgende Zeile gibt also True zurück.

set(v2).issubset(v1)

Um nach Duplikaten zu zählen, können Sie den folgenden Code verwenden:

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) 

Die folgende Zeile gibt also False zurück.

is_subseq(v2, v1)

1

Dies war, was ich online suchte, aber leider nicht online fand, sondern beim Experimentieren mit Python-Interpreter.

>>> case  = "caseCamel"
>>> label = "Case Camel"
>>> list  = ["apple", "banana"]
>>>
>>> (case or label) in list
False
>>> list = ["apple", "caseCamel"]
>>> (case or label) in list
True
>>> (case and label) in list
False
>>> list = ["case", "caseCamel", "Case Camel"]
>>> (case and label) in list
True
>>>

und wenn Sie eine lange Liste von Variablen in a haben sublist variable

>>>
>>> list  = ["case", "caseCamel", "Case Camel"]
>>> label = "Case Camel"
>>> case  = "caseCamel"
>>>
>>> sublist = ["unique banana", "very unique banana"]
>>>
>>> # example for if any (at least one) item contained in superset (or statement)
...
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
False
>>>
>>> sublist[0] = label
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>> # example for whether a subset (all items) contained in superset (and statement)
...
>>> # a bit of demorgan's law
...
>>> next((False for item in sublist if item not in list), True)
False
>>>
>>> sublist[1] = case
>>>
>>> next((False for item in sublist if item not in list), True)
True
>>>
>>> next((True for item in sublist if next((True for x in list if x == item), False)), False)
True
>>>
>>>

0

Ein Beispiel dafür, wie dies mit einem Lambda-Ausdruck gemacht wird, wäre:

issublist = lambda x, y: 0 in [_ in x for _ in y]

1
Bitte fügen Sie Kommentare hinzu, um Ihre Antwort zu erklären / auszuarbeiten
Sharad

0

Nicht der Fall von OP, aber - für alle, die Kreuzungen in Diktaten behaupten wollen und wegen schlechten Googelns hier gelandet sind (z. B. ich) - müssen Sie arbeiten mit dict.items:

>>> a = {'key': 'value'}
>>> b = {'key': 'value', 'extra_key': 'extra_value'}
>>> all(item in a.items() for item in b.items())
True
>>> all(item in b.items() for item in a.items())
False

Dies liegt daran, dass dict.itemsTupel von Schlüssel / Wert-Paaren zurückgegeben werden und wie jedes Objekt in Python austauschbar vergleichbar sind

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.