Seite 1 von 1

In Liste/Tupel im Kreis laufen

Verfasst: Donnerstag 14. April 2005, 10:33
von leoel
Hallo!

Wie würdet Ihr das möglichst elegant lösen:

Ihr habt eine Liste/Tuple von sagen wir 20 Einträgen. Jetzt brauche ich eine Art "RoundRobin", d.h ich will durch die 20 Einträge iterieren und nach dem 20. Eintrag wieder am Anfang starten, d.h. der 21. Zugriff liefert mir den 1.Eintrag

Ad hoc fällt mir folgende Möglichkeit ein: Mit "enumerate" und einer Modulo Funktion auf den Index zugreifen.

Gibt es noch was schöneres?

Danke, Leo

Verfasst: Donnerstag 14. April 2005, 12:47
von Leonidas
Ich könnt mir vorstellen, von list bzw. dict zu erben, um dort dann __getitem__ zu überschreiben, dass beim Zugriff auf object[21] der erste Eintrag kommt. Könnte auch völliger Schwachsinn sein... aber es klingt für mich zumindest ganz ok.

Verfasst: Donnerstag 14. April 2005, 21:31
von BlackJack
Hilft `itertools.cycle()` weiter?

Verfasst: Donnerstag 14. April 2005, 22:15
von raist1314
BlackJack hat geschrieben:Hilft `itertools.cycle()` weiter?
Zitat aus der Python Dokumentation:
Note, this member of the toolkit may require significant auxiliary storage (depending on the length of the iterable).
Ich würde dir eher zu einer kreisförmigen Liste raten oder du realisierst das Ganze ähnlich einer Queue. Also folgender Ablauf:
- Über die Liste laufen
- aktuelles Element von der Liste entfernen
- aktuelles Element hinten an die liste wieder anhängen

Dafür würde wohl eine eigene Klasse Sinn machen... Ich habs jetzt nicht ausprobiert, wie praktikabel das ganze ist... Vielleicht hilfts dir ja irgendwie... Ich schau mal, ob ich ein Beispiel hinkriege.

Sebastian

Verfasst: Donnerstag 14. April 2005, 22:31
von raist1314
Wenn ich mich nicht verdacht habe, kann man es mittels Queue lösen:

Code: Alles auswählen

import Queue
import time

q = Queue.Queue()
for in in xrange(0,10):
    q.put(i)

stop = False # variable zum anhalten
while not q.empty():
    if stop: break
    value = q.get() # aktuellen wert aus der queue holen
    print value
    q.put(value) # wird wieder in die queue packen
    # mach was mit value hier
    time.sleep(1)
Du musst natürlich noch Code einbauen, um die Variable stop zu setzen, damit du irgenwie die Schleife auch wieder Beenden kannst, sonst kannst du das Programm nur noch über <STRG>-C abbrechen.

Hoffe, ich konnte dir helfen...

Sebastian

Verfasst: Freitag 15. April 2005, 10:58
von rayo
Hi

Einfach List erweitern :)

Code: Alles auswählen

class Rotater(list):
    def __getitem__(self, value):
        return super(Rotater,self).__getitem__(value % len(self))

l = Rotater()
for x in range(10):
    l.append(x)

for x in range(60):
    print l[x]
Gruss

wow

Verfasst: Freitag 15. April 2005, 11:49
von leoel
Das sind echt tolle Vorschläge!

Vielen Dank, hat mir sehr geholfen...

Zusammenfassung:
- Liste überladen und mit Modulo arbeiten
- Liste mit POP und Append
- Mit der Queue arbeiten (ist logisch ähnlich zu Pop/Append)

super sache
lg Leo

Verfasst: Freitag 15. April 2005, 12:30
von Leonidas
Wie was das mit TMTOWTDI in Python? Sollte doch nicht sein ;)

Dumm nur, dass es schwer ist zu sagen, welcher Weg jetzt der "richtige" ist *g*.

Verfasst: Freitag 15. April 2005, 14:32
von leoel
ja, das hab ich mir auch gedacht....

Im Prinzip sind es aber zwei Ansätze:
a) "Kreise" mit dem Index
b) Verschiebe die Elemente von "vorne" nach "hinten"

Was jetzt "besser" ist, muss jeder für sich entscheiden, ich hab das für mich nach *Verständlichkeit* und *Einfachheit* beurteilt.

Weiters galt für mich das Gefühl, wie sich der Code "leichter" tut (ich weiss, klingt dämlich, ist aber so) und für mich war daher der Weg den Index zu verbiegen klarer also die Elemente zu verschieben.
(vermutlich wird im C-Code von Python ohnehin nur der Pointer verschoben).

Die Performance spielt bei 20-30 Einträgen vermutlich keine Rolle...

lg Leo

Verfasst: Samstag 16. April 2005, 23:33
von BlackJack
Ich würde sagen das indexieren modulo Länge der Liste ist der "richtige" Weg. Wegnehmen und anfügen bei einer Liste kann sehr "teuer" werden weil nicht nur ein Pointer bewegt werden muss, sondern alle Elemente (Pointer) der Liste.

Der Warnhinweis bei `itertools.cycle` gilt natürlich nicht wenn die Listen/Tupel klein sind. Es wird nochmal ungefähr der Speicherplatz für die Pointer in der Liste belegt. Und zwar beim ersten Durchgang. Bei jedem weiteren Zyklus wird intern wahrscheinlich auch modulo auf die angelegte Kopie zugegriffen.

Zum TMTOWTDI: Die Gegenhaltung bei einigen Pythonistas ist übertrieben. Im Zen steht nur `There should be one -- and preferebly only one -- obvious way to do it.`, also das es nur einen offensichtlichen Weg geben sollte, nicht muss. Ausserdem kann es sein, dass man Holländer sein muss, um den zu sehen. :wink:

das mit den Holländern...

Verfasst: Montag 18. April 2005, 07:42
von leoel
kenn ich nicht, ich bin aus Österreich, aber bei uns gibt es folgenden Spruch:
Warum einfach, wenn es kompliziert auch geht?
lg Leo