Ich brauche folgende Funktion:
Eingabe : alist
Ausgabe :
True
wenn alle Elemente in der Eingabeliste unter Verwendung des Standard-Gleichheitsoperators als gleich bewertet werden;False
Andernfalls.
Leistung : Natürlich ziehe ich es vor, keinen unnötigen Overhead zu verursachen.
Ich denke, es wäre am besten:
- Durchlaufen Sie die Liste
- Vergleichen Sie benachbarte Elemente
- und
AND
alle resultierenden Booleschen Werte
Aber ich bin mir nicht sicher, was der pythonischste Weg ist, das zu tun.
Das Fehlen einer Kurzschlussfunktion schmerzt nur bei einem langen Eingang (über ~ 50 Elemente), der frühzeitig ungleiche Elemente aufweist. Wenn dies häufig genug auftritt (wie oft hängt davon ab, wie lang die Listen sein können), ist der Kurzschluss erforderlich. Der beste Kurzschlussalgorithmus scheint @KennyTM zu sein checkEqual1
. Dies zahlt jedoch erhebliche Kosten:
- Bis zu 20x in nahezu identischen Leistungslisten
- Bis zu 2,5-fache Leistung auf Shortlists
Wenn die langen Eingänge mit frühen ungleichen Elementen nicht (oder nur selten genug) auftreten, ist kein Kurzschluss erforderlich. Dann ist die @ Ivo van der Wijk-Lösung bei weitem die schnellste.
a == b
oder identisch wie ina is b
?functools.reduce(operator.eq, a)
es nicht vorgeschlagen wurde.Antworten:
Allgemeine Methode:
Einzeiler:
Auch einzeilig:
Der Unterschied zwischen den 3 Versionen besteht darin, dass:
checkEqual2
dem Inhalt muss hashable sein.checkEqual1
undcheckEqual2
kann beliebige Iteratoren verwenden,checkEqual3
muss jedoch eine Sequenzeingabe vornehmen, normalerweise konkrete Container wie eine Liste oder ein Tupel.checkEqual1
stoppt, sobald ein Unterschied festgestellt wird.checkEqual1
mehr Python-Code enthält, ist es weniger effizient, wenn viele der Elemente am Anfang gleich sind.checkEqual2
undcheckEqual3
immer O (N) Kopiervorgänge durchführen, werden sie länger dauern , wenn die meisten Ihrer Eingabe falsch zurück.checkEqual2
undcheckEqual3
es ist schwieriger, den Vergleich vona == b
bis anzupassena is b
.timeit
Ergebnis für Python 2.7 und (nur s1, s4, s7, s9 sollten True zurückgeben)wir bekommen
Hinweis:
quelle
obj.__eq__
wennlhs is rhs
, und Out-of-Order - Optimierungen zu ermöglichen Kurzschlüsse Listen schneller sortierten.itertools
Rezept, das ich als Antwort hinzugefügt habe. Es könnte sich lohnen, das in deine Timing-Matrix zu werfen :-).Eine Lösung, die schneller ist als die Verwendung von set (), die mit Sequenzen (nicht iterablen) funktioniert, besteht darin, einfach das erste Element zu zählen. Dies setzt voraus, dass die Liste nicht leer ist (aber das ist trivial zu überprüfen und selbst zu entscheiden, was das Ergebnis auf einer leeren Liste sein soll)
einige einfache Benchmarks:
quelle
x.count(next(x)) == len(x)
damit es für jeden Container x funktioniert? Ahh .. nm, habe gerade gesehen, dass .count nur für Sequenzen verfügbar ist .. Warum ist es nicht für andere eingebaute Container implementiert? Ist das Zählen in einem Wörterbuch von Natur aus weniger sinnvoll als in einer Liste?count
nicht für iterables implementiert ist, nicht warumlen
nicht für Iteratoren verfügbar. Die Antwort ist wahrscheinlich, dass es nur ein Versehen ist. Für uns ist dies jedoch irrelevant, da die Standardeinstellung.count()
für Sequenzen sehr langsam ist (reines Python). Der Grund , warum Ihre Lösung so schnell ist , ist , dass es auf dem C-implementiertes beruht ,count
bereitgestellt durchlist
. Ich nehme also an, dass jedes iterierbarecount
Verfahren zur Implementierung der Methode in C von Ihrem Ansatz profitiert.Der einfachste und eleganteste Weg ist wie folgt:
(Ja, dies funktioniert sogar mit der leeren Liste! Dies liegt daran, dass dies einer der wenigen Fälle ist, in denen Python eine faule Semantik hat.)
In Bezug auf die Leistung wird dies zum frühestmöglichen Zeitpunkt fehlschlagen, so dass es asymptotisch optimal ist.
quelle
checkEqual1
. Ich bin mir nicht sicher warum.first=myList[0]
all(x==first for x in myList)
first=myList[0]
eineIndexError
auf eine leere Liste wirft , sodass Kommentatoren, die über diese von mir erwähnte Optimierung gesprochen haben, sich mit dem Randfall einer leeren Liste befassen müssen. Das Original ist jedoch in Ordnung (x==myList[0]
ist in Ordnung,all
da es niemals ausgewertet wird, wenn die Liste leer ist).Eine festgelegte Vergleichsarbeit:
Mit werden
set
alle doppelten Elemente entfernt.quelle
Sie können die Liste in einen Satz konvertieren. Ein Satz darf keine Duplikate enthalten. Wenn also alle Elemente in der ursprünglichen Liste identisch sind, enthält die Menge nur ein Element.
quelle
len(set(input_list)) == 1
?Für das, was es wert ist, wurde dies kürzlich auf die Python-Ideen-Mailingliste gesetzt . Es stellt sich heraus, dass es dafür bereits ein itertools-Rezept gibt : 1
Angeblich funktioniert es sehr gut und hat ein paar schöne Eigenschaften.
1 Mit anderen Worten, ich kann weder die Anerkennung für die Entwicklung der Lösung noch die Anerkennung dafür finden, dass ich sie überhaupt gefunden habe.
quelle
return next(g, f := next(g, g)) == f
(ab py3.8 natürlich)Hier sind zwei einfache Möglichkeiten, dies zu tun
mit set ()
Beim Konvertieren der Liste in einen Satz werden doppelte Elemente entfernt. Wenn also die Länge der konvertierten Menge 1 beträgt, bedeutet dies, dass alle Elemente gleich sind.
Hier ist ein Beispiel
mit all ()
Dadurch wird das erste Element der Eingabeliste mit jedem anderen Element in der Liste verglichen (Äquivalenz). Wenn alle gleichwertig sind, wird True zurückgegeben, andernfalls wird False zurückgegeben.
Hier ist ein Beispiel
PS Wenn Sie überprüfen, ob die gesamte Liste einem bestimmten Wert entspricht, können Sie den Wert für input_list [0] eingeben.
quelle
len(set(a))
dauerte die Ausführung einer Liste mit 10.000.000 Elementen 0,09 s, während die Ausführungall
0,9 s (zehnmal länger) dauerte.Dies ist eine weitere Option, schneller als
len(set(x))==1
bei langen Listen (verwendet Kurzschluss)quelle
Dies ist eine einfache Methode:
Dies ist etwas komplizierter, es entsteht ein Funktionsaufruf-Overhead, aber die Semantik ist klarer formuliert:
quelle
for elem in mylist[1:]
. Zweifelsohne verbessert es die Geschwindigkeit erheblich, da ich denke,elem[0] is elem[0]
dass der Dolmetscher diesen Vergleich wahrscheinlich sehr schnell durchführen kann.Überprüfen Sie, ob alle Elemente dem ersten entsprechen.
np.allclose(array, array[0])
quelle
Zweifel, dies ist die "pythonischste", aber so etwas wie:
würde den Trick machen.
quelle
for
Schleife kannif any(item != list[0] for item in list[1:]): return False
mit genau der gleichen Semantik pythonischer gestaltet werden .Wenn Sie an etwas Lesbarem interessiert sind (aber natürlich nicht so effizient), können Sie Folgendes versuchen:
quelle
Konvertieren Sie die Liste in die Menge und suchen Sie dann die Anzahl der Elemente in der Menge. Wenn das Ergebnis 1 ist, hat es identische Elemente, und wenn nicht, sind die Elemente in der Liste nicht identisch.
quelle
In Bezug auf die Verwendung
reduce()
mitlambda
. Hier ist ein Arbeitscode, den ich persönlich für viel schöner halte als einige der anderen Antworten.Gibt ein Tupel zurück, bei dem der erste Wert der Boolesche Wert ist, wenn alle Elemente gleich sind oder nicht.
quelle
[1, 2, 2]
): Der vorherige boolesche Wert wird nicht berücksichtigt. Dies kann durch Ersetzen fixiert werdenx[1] == y
mitx[0] and x[1] == y
.Ja, würde ich:
as
any
hört auf, das iterable zu suchen, sobald es eineTrue
Bedingung findet.quelle
all()
, verwenden warum nichtall(x == seq[0] for x in seq)
? sieht pythonischer aus und sollte das gleiche tunquelle
Funktioniert in Python 2.4, das nicht "alle" enthält.
quelle
for k in j: break
ist äquivalent zunext(j)
. Sie hätten es auch tun können,def allTheSame(x): return len(list(itertools.groupby(x))<2)
wenn Sie sich nicht um Effizienz gekümmert hätten.Kann Karte und Lambda verwenden
quelle
Oder verwenden Sie die
diff
Methode der Numpy:Und um anzurufen:
Ausgabe:
quelle
not np.any(np.diff(l))
könnte ein bisschen schneller sein.Oder verwenden Sie die diff-Methode von numpy:
Und um anzurufen:
Ausgabe:
Wahr
quelle
Du kannst tun:
Es ist ziemlich ärgerlich, dass Sie mit Python die Operatoren wie importieren
operator.and_
. Ab Python3 müssen Sie auch importierenfunctools.reduce
.(Sie sollten diese Methode nicht verwenden, da sie nicht unterbrochen wird, wenn ungleiche Werte gefunden werden, sondern die gesamte Liste weiter untersucht. Sie wird hier nur als Antwort auf Vollständigkeit aufgeführt.)
quelle
Der nächste wird kurzschließen:
quelle
reduce(lambda a,b:a==b, [2,2,2])
ergibtFalse
... Ich habe ihn bearbeitet, aber auf diese Weise ist er nicht mehr schönÄndern Sie die Liste in einen Satz. Wenn die Größe des Sets nur 1 beträgt, müssen sie gleich gewesen sein.
quelle
Es gibt auch eine reine rekursive Python-Option:
Aus irgendeinem Grund ist es jedoch in einigen Fällen zwei Größenordnungen langsamer als andere Optionen. Ich komme aus der C-Sprachmentalität und habe erwartet, dass dies schneller geht, aber das ist es nicht!
Der andere Nachteil ist, dass es in Python eine Rekursionsgrenze gibt, die in diesem Fall angepasst werden muss. Zum Beispiel mit diesem .
quelle
Sie können verwenden
.nunique()
, um die Anzahl der eindeutigen Elemente in einer Liste zu finden.quelle
Sie können verwenden
set
. Es wird ein Satz erstellt und sich wiederholende Elemente entfernt. Überprüfen Sie dann, ob es nicht mehr als 1 Element enthält.Beispiel:
quelle