Vermeiden Objekt aliasing in python?
Ich versuche, eine Funktion schreiben, die überprüfen, ob eine Liste sortiert ist (Rückkehr True
oder False
). Wie kann ich vermeiden, dass mehrere Variablen auf das gleiche Ding?
def is_sorted(t):
a = t
a.sort()
Wenn ich das mache, er sortiert beide a
und t
. Wie kann ich diese vermeiden?
- "Wie kann ich diese vermeiden?" Von der Suche nach einem besseren design. Dies ist -- vielleicht -- die langsamste Art und Weise, dies zu tun. Die einzige Sache, die könnte langsamer sein, wäre die Umsetzung Ihrer eigenen version von
sort
. - Es ist etwas, das erkenntnistheoretische über die Antworten, die beinhalten, dass die Sortierung der Liste: es ist völlig unwahrscheinlich, dass das Programm keine Verwendung haben für, zu einem anderen Ergebnis als
True
nachdem die Liste bereits sortiert. Nur in sehr seltenen Fällen würde die Antwort auf die ursprünglicheis_sorted()
Abfrage noch relevant sein. Außerdem, ist die Sortierung einer bereits sortierten Liste ist nah genug zu A(n), also Warum die Mühe Abfragen, anstatt nur geradeaus und ruftsort()
odersorted()
?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Hier ist das O(n) Weg, es zu tun
Es zu Kurzschlüssen, so dass, wenn die Liste unsortiert direkt in der Nähe der Anfang, es wird sehr schnell
Hier ist ein einfaches Programm zum vergleichen einige der alternativen
izip(L, islice(L,1,None))
Folien ein Fenster überL
. Es gibt eine Reihenfolge wie[(L[0],L[1]), (L[1],L[2]), ...]
timeit
- und post-Vergleich zeigt, was wirklich passiert ist, nicht das, was sollte geschehen.xrange
inteadrange
range
stattxrange
war ein Anfänger-Fehler (xrange verworfen wurde in Python 3).xrange
bekannt ist. "die Indizierung einer Python-Liste sollte viel billiger sein, als das schneiden und komprimieren es" nicht so bekannt ist. Ohne aktuelle zahlen, ist es-tatsächlich-Vermutung. Mit tatsächlichen zahlen ist es Theorie + Beweise == Wissenschaft.BEARBEITEN: siehe diese Antwort für den richtigen Weg, es zu tun. Ich lasse meine Antwort hier für die Nachwelt (was ist der richtige Weg, diese situation zu bewältigen?), aber es sollte nicht als die beste Antwort auf die Frage, auch wenn es ein richtige Antwort auf die Frage.
Beantworten Ihre spezifische Frage, die Sie verwenden können
copy.copy
(oder verwenden Sie das slice-syntax[:]
) erstellen Sie eine Kopie der ursprünglichen Liste:Jedoch eine bessere Methode wäre, um die
sorted
- Funktion geben Sie eine sortierte Kopie der Liste:Oder:
is_sorted = lambda t: sorted(t) == t
deepcopy
übertrieben ist, angesichts der specs.copy
oder[:]
genügen, da die Elemente in der Liste nicht geändert wird.durch die Schaffung einer Kopie Ihrer Liste mit so etwas wie dies:
Kredit für diese minimale Antwort gehört @gnibbler
all()
hier statt reduzieren und der code wird übersichtlicher zu.all(q[i] < q[i+1] for i in range(len(q)-1))
and_
- operator wertet in Kurzschluss-Mode: es wird verbrauchen die input-iterator während es findetTrue
. Eine Lösung mitall
ist besser.reduce()
nicht weiß, dass es aufhören kann, wenn es feststellt, Wahr ist, so dass der generator-Ausdruck würde müssen vollständig, bis zum Ende.reduce()
. Meine Antwort wurde bereits von Ihnen positiv bewertet werden, so korrigierte ich ihn. Die Kommentare und Ihre Antworten enthalten, die Spur von Veränderungen, außer meiner ursprünglichenreduce(operator.and_, q[i] < q[i+1] for i in range(len(q)-1))
Können Sie entweder eine Kopie der
t
und dann Sortieren, etwa so:a = t[:]
oder verwendensortiert
, das gibt eine neue sortierte Liste.Alternativ nutzen Sie die
sortedlist
Struktur von blist, dann wird Ihre Liste immer sortiert werden.Dies ist eine sehr schlechte Art und Weise, hinsichtlich der Leistung, zu überprüfen, ob eine Liste geordnet ist. Sie sollten stattdessen Durchlaufen Sie überprüfen, dass jedes element größer oder gleich dem vorherigen.
list.sort
odersorted
. Wenn es eine Art nur, wenn die unsortierte situation, dann TimSort (der Sortier-Algorithmus verwendet, um Python) ist O(n) auf einer sortierten Liste, die ist, was die Prüfung für Monotonie über ist, um mit zu beginnen. Also nochmal, einfach die Liste Sortieren.