Ich muss überprüfen, ob eine Liste eine Teilmenge einer anderen ist - eine boolesche Rückgabe ist alles, was ich suche.
Ist das Testen der Gleichheit auf der kleineren Liste nach einer Kreuzung der schnellste Weg, dies zu tun? Die Leistung ist angesichts der Anzahl der zu vergleichenden Datensätze von größter Bedeutung.
Hinzufügen weiterer Fakten basierend auf Diskussionen:
Wird eine der Listen für viele Tests gleich sein? Es handelt sich um eine statische Nachschlagetabelle.
Muss es eine Liste sein? Dies ist nicht der Fall - die statische Nachschlagetabelle kann alles sein, was am besten funktioniert. Das dynamische ist ein Diktat, aus dem wir die Schlüssel extrahieren, um eine statische Suche durchzuführen.
Was wäre angesichts des Szenarios die optimale Lösung?
Antworten:
Die performante Funktion, die Python dafür bereitstellt, ist
set.issubset
. Es gibt jedoch einige Einschränkungen, die unklar machen, ob dies die Antwort auf Ihre Frage ist.Eine Liste kann Elemente mehrmals enthalten und hat eine bestimmte Reihenfolge. Ein Set nicht. Außerdem funktionieren Sets nur für hashbare Objekte.
Fragen Sie nach Teilmengen oder Teilsequenzen (was bedeutet, dass Sie einen String-Suchalgorithmus wünschen)? Wird eine der Listen für viele Tests gleich sein? Welche Datentypen sind in der Liste enthalten? Und muss es eine Liste sein?
Ihr anderer Beitrag schneidet ein Diktat und eine Liste , um die Typen klarer zu machen, und erhielt die Empfehlung, Wörterbuchschlüsselansichten für ihre satzähnliche Funktionalität zu verwenden. In diesem Fall war bekannt, dass es funktioniert, weil sich Wörterbuchschlüssel wie eine Menge verhalten (so sehr, dass wir Wörterbücher verwendeten, bevor wir Mengen in Python hatten). Man fragt sich, wie das Problem in drei Stunden weniger spezifisch wurde.
quelle
quelle
set(a).issubset(b)
weil Sie in diesem Fall nura
in set konvertieren , aber nichtb
, was Zeit spart. Sie könnentimeit
die in zwei Befehlen verbrauchte Zeit vergleichen. Zum Beispieltimeit.repeat('set(a)<set(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000)
undtimeit.repeat('set(a).issubset(b)', 'a = [1,3,5]; b = [1,3,5,7]', number=1000)
issubset
set
frozenset
set
set
Sie tun müssen, ist zu überprüfen, ob das Argument ein / ist , und wenn dies nicht der Fall ist , konvertiert es es zum Vergleich in ein temporäres Argument , führt die Überprüfung aus und wirft das temporäre dann weg . Zeitliche Unterschiede (falls vorhanden) sind ein Faktor für kleine Unterschiede bei den LEGB-Suchkosten (set
ein zweites Mal zu finden ist teurer als die Attributsuche bei einem vorhandenenset
), aber es ist meistens eine Wäsche für ausreichend große Eingaben.Erläuterung: Der Generator erstellt Boolesche Werte, indem er die Liste durchläuft und
one
prüft, ob sich dieses Element in der Liste befindettwo
. Gibtall()
zurück,True
wenn jeder Artikel wahr istFalse
.Es gibt auch den Vorteil, dass
all
False bei der ersten Instanz eines fehlenden Elements zurückgegeben wird, anstatt jedes Element verarbeiten zu müssen.quelle
set(one).issubset(set(two))
ist dies eine großartige Lösung. Mit der von mir veröffentlichten Lösung sollten Sie sie mit allen Objekten verwenden können, wenn für sie die richtigen Vergleichsoperatoren definiert sind.all
einen ordnungsgemäßen Kurzschluss, letzteres führt alle Überprüfungen durch, auch wenn aus der ersten Überprüfung hervorgeht, dass der Test fehlschlagen würde. Lassen Sie einfach die eckigen Klammern fallen, um zu erhaltenall(x in two for x in one)
.Angenommen, die Elemente sind hashbar
Wenn Sie sich nicht für doppelte Elemente interessieren, z.
[1, 2, 2]
und[1, 2]
dann einfach benutzen:.issubset
wird der schnellste Weg sein, dies zu tun. Das Überprüfen der Länge vor dem Testenissubset
verbessert die Geschwindigkeit nicht, da Sie noch O (N + M) -Elemente durchlaufen und überprüfen müssen.quelle
Eine weitere Lösung wäre die Verwendung von a
intersection
.Der Schnittpunkt der Mengen würde von enthalten
set one
(ODER)
quelle
Wenn Liste1 in Liste 2 enthalten ist:
(x in two for x in one)
generiert eine Liste vonTrue
.Wenn wir dies tun,
set(x in two for x in one)
hat a nur ein Element (True).quelle
Die Mengenlehre ist für Listen ungeeignet, da Duplikate mit der Mengenlehre zu falschen Antworten führen.
Beispielsweise:
Hat keine Bedeutung. Ja, es gibt eine falsche Antwort, aber dies ist nicht korrekt, da die Mengenlehre nur vergleicht: 1,3,5 gegenüber 1,3,4,5. Sie müssen alle Duplikate einschließen.
Stattdessen müssen Sie jedes Vorkommen jedes Elements zählen und eine Prüfung durchführen, die größer als gleich ist. Dies ist nicht sehr teuer, da keine O (N ^ 2) -Operationen verwendet werden und keine schnelle Sortierung erforderlich ist.
Wenn Sie dies ausführen, erhalten Sie:
quelle
Verzeihen Sie mir, wenn ich zu spät zur Party komme. ;)
Um zu überprüfen, ob eine
set A
Teilmenge von istset B
,Python
hatA.issubset(B)
undA <= B
. Es funktioniertset
nur und funktioniert hervorragend, ABER die Komplexität der internen Implementierung ist unbekannt. Referenz: https://docs.python.org/2/library/sets.html#set-objectsIch habe einen Algorithmus entwickelt, um zu überprüfen, ob
list A
es sich um eine Teilmenge derlist B
folgenden Anmerkungen handelt.sort
beide Listen zu vergleichen, bevor Elemente verglichen werden, um sich für Teilmengen zu qualifizieren.break
das ,loop
wenn der Wert des Elements der zweiten ListeB[j]
ist größer als der Wert des Elements der ersten ListeA[i]
.last_index_j
wird verwendet , um Startloop
über ,list B
wo er aus dem letzten links. Es hilft vermeiden Vergleiche ausgehend vom Beginnlist B
(das ist, wie Sie unnötige vorstellen können, startenlist B
ausindex 0
in der Folgeiterations
.)Die Komplexität besteht
O(n ln n)
jeweils darin, beide Listen zu sortieren undO(n)
nach Teilmengen zu suchen.O(n ln n) + O(n ln n) + O(n) = O(n ln n)
.Code hat viele
print
Anweisungen, um zu sehen, was bei jedemiteration
der beiden los istloop
. Diese sind nur zum Verständnis gedacht.Überprüfen Sie, ob eine Liste Teil einer anderen Liste ist
Ausgabe
quelle
Der folgende Code prüft, ob eine bestimmte Menge eine "richtige Teilmenge" einer anderen Menge ist
quelle
In Python 3.5 können Sie a ausführen
[*set()][index]
, um das Element abzurufen. Es ist eine viel langsamere Lösung als andere Methoden.oder einfach mit len und set
quelle
Hier ist, woher ich weiß, ob eine Liste eine Teilmenge einer anderen ist, die Reihenfolge ist mir in meinem Fall wichtig.
quelle
Die meisten Lösungen berücksichtigen, dass die Listen keine Duplikate enthalten. Falls Ihre Listen Duplikate enthalten, können Sie Folgendes versuchen:
Es stellt sicher, dass die Unterliste niemals andere Elemente als die Liste oder eine größere Menge eines gemeinsamen Elements enthält.
quelle
Da niemand über einen Vergleich mit Zeichenfolgen nachgedacht hat, ist hier mein Vorschlag.
Sie können natürlich überprüfen, ob die Pipe ("|") nicht Teil einer der beiden Listen ist, und möglicherweise automatisch ein anderes Zeichen auswählen, aber Sie haben die Idee.
Die Verwendung einer leeren Zeichenfolge als Trennzeichen ist keine Lösung, da die Zahlen mehrere Ziffern haben können ([12,3]! = [1,23]).
quelle
Wenn Sie fragen, ob eine Liste in einer anderen Liste "enthalten" ist, dann:
Wenn Sie fragen, ob jedes Element in Liste A die gleiche Anzahl übereinstimmender Elemente in Liste B enthält, versuchen Sie Folgendes:
quelle
Wenn ja
a2 is subset of a1
, dannLength of set(a1 + a2) == Length of set(a1)
quelle