Was macht dieser Code ?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
PeterL
User
Beiträge: 95
Registriert: Samstag 6. März 2021, 18:39

Hallo Leute,

ich habe ein Codebeispiel aus dem Internet.
Es wird eine Liste mit Zahlen gemischt.
Leider kann ich es nicht nachvollziehen wie der Code funktioniert .
Kann mir jemand erklären wie die Zahlen gemischt werden. ?

Code: Alles auswählen

import random 
  
test_list = [1, 4, 5, 6, 3] 
  
print ("The original list is : " + str(test_list)) 
  
for i in range(len(test_list)-1, 0,-1): 
      
    
    j = random.randint(0, i + 1)
    
    
    
    test_list[i], test_list[j] = test_list[j], test_list[i]  
      
print ("The shuffled list is : " +  str(test_list)) 
Bis dann...
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Was genau verstehst Du nicht? Wenn Du nachvollziehen willst, was passiert, dann gib in jedem Schleifenschritt i, j, und test_list aus.
PeterL
User
Beiträge: 95
Registriert: Samstag 6. März 2021, 18:39

Sirius3 hat geschrieben: Dienstag 22. November 2022, 14:45 Was genau verstehst Du nicht? Wenn Du nachvollziehen willst, was passiert, dann gib in jedem Schleifenschritt i, j, und test_list aus.
Hallo,

was bedeutet das:

Code: Alles auswählen

for i in range(len(test_list)-1, 0,-1): 
      
   
    
Wozu -1,0,-1 ???

Bis dann...
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

PeterL hat geschrieben: Dienstag 22. November 2022, 14:52 Wozu -1,0,-1 ???
Da muss man sich wohl mal in der Python-Dokumentation range anschauen. Bei drei Parametern heißen diese start, stop und step. Wir haben also einen Startwert von len(list)-1, einen Endwert von 0 (exklusive) und eine Schrittweite von -1. Lass dir in der Schleife doch einfach mal i ausgeben.

Die gesamte Routine als solche ist natürlich nicht erforderlich. Da würde man eher random.shuffle verwenden.
PeterL
User
Beiträge: 95
Registriert: Samstag 6. März 2021, 18:39

/me hat geschrieben: Dienstag 22. November 2022, 15:02
PeterL hat geschrieben: Dienstag 22. November 2022, 14:52 Wozu -1,0,-1 ???
Da muss man sich wohl mal in der Python-Dokumentation range anschauen. Bei drei Parametern heißen diese start, stop und step. Wir haben also einen Startwert von len(list)-1, einen Endwert von 0 (exklusive) und eine Schrittweite von -1. Lass dir in der Schleife doch einfach mal i ausgeben.
Hallo, es sieht so aus als würde die Liste rückwärts durchlaufen werden.
Er liest die Indexnummern rückwärts ein.

ich habe einen Linke gefunden.
Ich weis nun was der Code macht.
https://www.geeksforgeeks.org/shuffle- ... orithm/

Bis dann...
Zuletzt geändert von PeterL am Dienstag 22. November 2022, 16:13, insgesamt 1-mal geändert.
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@PeterL: Der Algorithmus hat auch einen Namen: Fisher-Yates-Verfahren. Da findet man sicher sowohl Beschreibungen als auch Implementierungen in allen möglichen Programmiersprachen im Netz.

Ich finde ja Leute die so etwas wie ``range(len(items) - 1, 0, -1)`` schreiben, sollte man wüst beschimpfen. Ich muss über so etwas auch immer wieder erst nachdenken und schreibe ``reversed(range(1, len(items)))`` stattdessen.

`random.shuffle()` verwendet übrigens auch das Fisher-Yates-Verfahren und auch `reversed()`.

Bei einer Zuweisung können Links vom Gleichheitszeichen so viele Ziele stehen wie rechts davon Werte stehen. Also genaugenommen muss rechts ein iterierbares Objekt stehen, das entsprechend viele Werte liefert wie links Ziele stehen:

Code: Alles auswählen

In [12]: a, b = 42, 23

In [13]: a
Out[13]: 42

In [14]: b
Out[14]: 23
Und jetzt kannst Du mal überlegen (und ausprobieren) was wohl so etwas wie ``a, b = b, a`` bedeutet.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
PeterL
User
Beiträge: 95
Registriert: Samstag 6. März 2021, 18:39

__blackjack__ hat geschrieben: Dienstag 22. November 2022, 16:09 @PeterL: Der Algorithmus hat auch einen Namen: Fisher-Yates-Verfahren.
Ich muss über so etwas auch immer wieder erst nachdenken und schreibe ``reversed(range(1, len(items)))`` stattdessen.

`random.shuffle()` verwendet übrigens auch das Fisher-Yates-Verfahren und auch `reversed()`.

Und jetzt kannst Du mal überlegen (und ausprobieren) was wohl so etwas wie ``a, b = b, a`` bedeutet.
Hallo,

danke für deine Infos.
Den Befehl reversed kannte ich noch nicht.
Ist das nicht ein Arbeitsaufwand zu viel, erst die Liste umdrehen und dann wird die Liste durchlaufen.?
Ist es nicht schneller die Liste gleich von hinten nach frone zu durchlaufen.?
random.shuffle kenne ich, das er auch das Fisher-Yates-Verfahren benutzt Wuste ich nicht.
Mich interessiert, was wohl schneller ist random.shuffle , oder das Fisher-Yates-Verfahren bei sehr großen listen, also den Code den ich gepostet habe.

Bis dann...
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

@PeterL: Dein Code ist zudem kaputt. Also das kaputte Fisher-Yates-Verfahren. Also nicht einfach alles, was man so im Internet findet, kopieren.

Und wie es CPython macht, kann man einfach im Quellcode nachlesen: https://github.com/python/cpython/blob/ ... om.py#L343
Benutzeravatar
__blackjack__
User
Beiträge: 13111
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@PeterL: Da wird nirgends eine Liste erstellt und dementsprechend auch keine umgedreht. `range()` erstellt ein `range`-Objekt das konstante Grösse hat, also egal wie gross der Zahlenbereich ist, immer gleich viel Speicher belegt. Und `reversed()` fragt das Argument nach einem „reverse iterator“. Den liefern `range`-Objekte — und der muss da auch keine Liste erstellen und umdrehen, denn genau wie bei der Vorwärtsrichtung lassen sich auch die Elemente in umgekehrter Reihenfolge relativ leicht berechnen/erzeugen.

Sollte das Argument keinen „reverse iterator“ liefern können, versucht `reversed()` noch ob es sich um eine Sequenz handelt, also ob das Argument eine Länge hat (`len()`) und ob es bei Indexzugriffen von `len(sequence)-1` bis 0 Werte liefert. Auch das ist ohne zusätzlichen Speicher für eine Liste und umdrehen derselben möglich.

Falls man beliebige iterierbare Objekte jenseits von ”reversible” Objekten und Sequenzen in umgekehrter Reihenfolge iterieren möchte, gibt es beispielsweise `more_itertools.always_reversible()`. Das braucht dann aber tatsächlich Speicher für alle Elemente, falls es nicht anders geht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Antworten