Ich habe eine sortierte Liste, sagen wir: (Es sind nicht nur Zahlen, sondern eine Liste von Objekten, die mit einem komplizierten zeitaufwändigen Algorithmus sortiert werden.)
mylist = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ,9 , 10 ]
Gibt es eine Python-Funktion, die mir N der Elemente gibt, aber die Reihenfolge beibehält?
Beispiel:
randomList = getRandom(mylist,4)
# randomList = [ 3 , 6 ,7 , 9 ]
randomList = getRandom(mylist,4)
# randomList = [ 1 , 2 , 4 , 8 ]
etc...
python
list
random
sortedlist
Yochai Timmer
quelle
quelle
random.sample
und dann sortieren?[0,count)
, sortieren Sie die Stichprobe (die Zahlen im Bereich haben eine natürliche Reihenfolge) und extrahieren Sie dann die Wertemylist
basierend auf den Indizes. Die Verwendungzip
könnte den gleichen Effekt mit leicht unterschiedlichen Mechaniken erzielen.Antworten:
Der folgende Code generiert eine Zufallsstichprobe der Größe 4:
(Hinweis: Mit Python 2 besser verwenden
xrange
alsrange
)Erläuterung
generiert eine zufällige Stichprobe der Indizes der ursprünglichen Liste.
Diese Indizes werden dann sortiert, um die Reihenfolge der Elemente in der ursprünglichen Liste beizubehalten.
Schließlich zieht das Listenverständnis die tatsächlichen Elemente aus der ursprünglichen Liste heraus, wenn die Stichprobenindizes gegeben sind.
quelle
Einfach zu codierender O (N + K * log (K)) Weg
Nehmen Sie eine Zufallsstichprobe ohne Ersatz der Indizes, sortieren Sie die Indizes und entnehmen Sie sie dem Original.
Oder genauer:
Optimierte O (N) -Zeit, O (1) -Intiliilraum-Weg
Sie können alternativ einen mathematischen Trick und iterativ durchläuft
myList
von links nach rechts, Kommissionierung Zahlen mit dynamisch wechselnden Wahrscheinlichkeit(N-numbersPicked)/(total-numbersVisited)
. Der Vorteil dieses Ansatzes ist, dass es sich um einenO(N)
Algorithmus handelt, da keine Sortierung erforderlich ist!Proof of Concept und Test der Richtigkeit der Wahrscheinlichkeiten :
Simuliert mit 1 Billion Pseudozufallsstichproben über einen Zeitraum von 5 Stunden:
Die Wahrscheinlichkeiten weichen um einen Faktor von 1.0001 von den tatsächlichen Wahrscheinlichkeiten ab. Das erneute Ausführen dieses Tests führte zu einer anderen Reihenfolge, was bedeutet, dass er nicht auf eine Bestellung ausgerichtet ist. Durchführen des Tests mit weniger Proben für
[0,1,2,3,4], k=3
und[0,1,2,3,4,5], k=4
ähnliche Ergebnisse.edit: Ich bin mir nicht sicher, warum Leute falsche Kommentare abgeben oder Angst haben, zu stimmen ... NEIN, an dieser Methode ist nichts auszusetzen. =)
(Auch ein nützlicher Hinweis von Benutzer tegan in den Kommentaren: Wenn dies python2 ist, sollten Sie xrange wie gewohnt verwenden, wenn Sie sich wirklich für zusätzlichen Speicherplatz interessieren.)
edit : Beweis: In Anbetracht der gleichmäßigen Verteilung (ohne Ersatz) der Auswahl einer Teilmenge
k
aus einer Populationseq
von Größelen(seq)
können wir eine Partition an einem beliebigen Punkti
in 'links' (0,1, ..., i-1) betrachten. und 'richtig' (i, i + 1, ..., len (seq)). Da wirnumbersPicked
aus der linken bekannten Teilmenge ausgewählt haben, müssen die verbleibenden aus derselben gleichmäßigen Verteilung in der rechten unbekannten Teilmenge stammen, obwohl die Parameter jetzt unterschiedlich sind. Insbesondere ist die Wahrscheinlichkeit,seq[i]
die ein ausgewähltes Element enthält,#remainingToChoose/#remainingToChooseFrom
, oder(k-numbersPicked)/(len(seq)-i)
Also simulieren wir das und greifen auf das Ergebnis zurück. (Dies muss beendet werden, da bei #remainingToChoose == #remainingToChooseFrom alle verbleibenden Wahrscheinlichkeiten 1 sind.) Dies ähnelt einem Wahrscheinlichkeitsbaum, der zufällig dynamisch generiert wird. Grundsätzlich können Sie eine gleichmäßige Wahrscheinlichkeitsverteilung simulieren, indem Sie auf vorherige Entscheidungen konditionieren (wenn Sie den Wahrscheinlichkeitsbaum vergrößern, wählen Sie die Wahrscheinlichkeit des aktuellen Zweigs so aus, dass sie aposteriori mit früheren Blättern identisch ist, dh von vorherigen Entscheidungen abhängig ist; dies funktioniert, weil diese Wahrscheinlichkeit ist einheitlich genau N / k).edit : Timothy Shields erwähnt Reservoir Sampling , die Verallgemeinerung dieser Methode, wenn sie
len(seq)
unbekannt ist (z. B. mit einem Generatorausdruck). Insbesondere ist der als "Algorithmus R" bezeichnete O (N) - und O (1) -Raum, wenn er an Ort und Stelle durchgeführt wird; Dabei wird das erste N-Element genommen und langsam ersetzt (ein Hinweis auf einen induktiven Beweis wird ebenfalls gegeben). Auf der Wikipedia-Seite finden Sie auch nützliche verteilte Varianten und verschiedene Varianten der Reservoir-Probenahme.Bearbeiten : Hier ist eine andere Möglichkeit, es unten semantisch offensichtlicher zu codieren.
)
quelle
O(N)
eherO(N log(N))
from __future__ import division
für diejenigen hinzuzufügen , die Python 2Vielleicht können Sie einfach die Stichprobe von Indizes generieren und dann die Elemente aus Ihrer Liste sammeln.
quelle
Anscheinend
random.sample
wurde in Python 2.3 eingeführtFür die Version darunter können wir also Shuffle verwenden (Beispiel für 4 Elemente):
quelle
random.sample implementieren es.
quelle