Liste wieder und wieder durchlaufen bis die Anzahl der zurückgegebenen Elemente stimmt
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
Hallo
Ich würde gerne die Elemente einer Liste mit 12 Einträgen immer wieder durchlaufen. Sobald das Ende der Liste erreicht ist, sollte der Durchlauf wieder von vorne beginnen, aber insgesamt sollen nur 1000 Werte ausgegeben werden. Die Liste müsste also 83 mal komplett durchlaufen und beim 84. Durchlauf beim 4. Element abgebrochen werden.
Bietet Python eine passende Funktion dafür an?
Gruß
Atalanttore
Ich würde gerne die Elemente einer Liste mit 12 Einträgen immer wieder durchlaufen. Sobald das Ende der Liste erreicht ist, sollte der Durchlauf wieder von vorne beginnen, aber insgesamt sollen nur 1000 Werte ausgegeben werden. Die Liste müsste also 83 mal komplett durchlaufen und beim 84. Durchlauf beim 4. Element abgebrochen werden.
Bietet Python eine passende Funktion dafür an?
Gruß
Atalanttore
Eine mögliche Variante:
Code: Alles auswählen
In [1]: from itertools import cycle
In [2]: def repeat(items, limit):
...: items = cycle(items)
...: for i in range(limit):
...: yield next(items)
...:
In [3]: l = [1,2,3]
In [4]: list(repeat(l, 5))
Out[4]: [1, 2, 3, 1, 2]
- __blackjack__
- User
- Beiträge: 13110
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@nezzcarth: Aber es gibt doch `islice()`, warum programmierst Du das noch mal in abgespeckter Form nach und benennst das dann auch noch wie eine andere Funktion aus `itertools` die etwas anderes macht?
Code: Alles auswählen
In [174]: l = [1,2,3]
In [175]: list(islice(cycle(l), 5))
Out[175]: [1, 2, 3, 1, 2]
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Eine interessante Variante kann man mit einem Generator bauen:
Edit: meine Eingabe hat sich mit obigen Antworten überschnitten, hier ein schöner handgestrickter Generator, ohne import schnickschnack
Edit: meine Eingabe hat sich mit obigen Antworten überschnitten, hier ein schöner handgestrickter Generator, ohne import schnickschnack
Code: Alles auswählen
def my_generator(my_list, count):
counter = count + 1
while counter > 0:
for item in my_list:
counter -= 1
if counter > 0:
yield item
output = my_generator([1,2,3,4,5,6,7,8,9,10,11,12], 1000)
for i in range(1000):
print(f'{next(output)} ', end='')
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
@__blackjack__: Offensichtlich, weil ich es nicht besser wusste (an islice habe ich nicht gedacht und außer cycle oder repeat wüsste ich nicht, wie man es groß anders nennen soll; repeat wird ja zumindest nicht verwendet).
Verstehe ich diese Lösung so, dass hier eine Liste mit 1000 Elementen erzeugt wird, über die man dann iterieren muss?__blackjack__ hat geschrieben: ↑Sonntag 1. Juli 2018, 17:12Code: Alles auswählen
In [174]: l = [1,2,3] In [175]: list(islice(cycle(l), 5)) Out[175]: [1, 2, 3, 1, 2]
Wenn ja, nicht sehr ökonomisch.
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
islice gibt einen Iterator zurück. Die Umwandlung in eine Liste war zumindest in meinem Beispiel (das __blackjack__ verbessert hat) nur zur Illustration gedacht; eine Schleife mit einem Dummy-Print nimmt mehr Platz weg.
@ThomasL: Import-Schnickschnack ist genau dafür da, dass man nicht jeden Bling selbst schreiben muß. Nicht sehr ökonomisch ist an Deiner Lösung, dass die Liste immer komplett durchlaufen wird. Schönheit definiert ja jeder anders, z.B. die for-range-Schleife.
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
Danke für die vielen Antworten.
Gruß
Atalanttore
Gruß
Atalanttore
@Sirius3 Du hast die ursprüngliche Fragestellung gelesen?
Ich habe einen konfigurierbaren Generator, die Liste die immer wieder durchlaufen werden soll
und die Anzahl der Werte die ausgegeben werden sollen können angegeben werden.
Die for-schleife ist nur ein Beispiel um zu zeigen, wie man jetzt die einzelnen Werte (in dem Beispiel mit next() ) abruft.
Selbstverständlich ist diese Lösung hier eleganter:
Was stört dich jetzt bitte an meinem Beispiel Ausgabecode, dass er alle Elemente ausgibt? Hä??Atalanttore hat geschrieben: ↑Sonntag 1. Juli 2018, 16:28 Hallo, Ich würde gerne die Elemente einer Liste mit 12 Einträgen immer wieder durchlaufen. Sobald das Ende der Liste erreicht ist, sollte der Durchlauf wieder von vorne beginnen, aber insgesamt sollen nur 1000 Werte ausgegeben werden. Die Liste müsste also 83 mal komplett durchlaufen und beim 84. Durchlauf beim 4. Element abgebrochen werden.
Bietet Python eine passende Funktion dafür an? Gruß Atalanttore
Ich habe einen konfigurierbaren Generator, die Liste die immer wieder durchlaufen werden soll
und die Anzahl der Werte die ausgegeben werden sollen können angegeben werden.
Die for-schleife ist nur ein Beispiel um zu zeigen, wie man jetzt die einzelnen Werte (in dem Beispiel mit next() ) abruft.
Selbstverständlich ist diese Lösung hier eleganter:
Code: Alles auswählen
for item in output:
print(f'{item} ', end='')
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
@ThomasL: Wenn es Dir um Ökonomie geht, dann nimm:
Sicher sind eigene Generatoren schön, aber noch schöner ist es, wenn man sich bereits der builtins und aus der Standard-Library bedienen kann.
Code: Alles auswählen
for n in islice(cycle(range(12), 1000):
...
- __blackjack__
- User
- Beiträge: 13110
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@ThomasL: Bei Deiner Lösung stört, dass die Liste auch in den Fällen komplett durchlaufen wird wo gar nicht alle Elemente benötigt werden. Wenn man 1000 Elemente übergibt und 1005 haben möchte, wird die ``for``-Schleife *in* der Funktion 2000 mal durchlaufen. Das sind 1995 mal mehr als nötig wären. Klar kann man das jetzt fixen — man kann aber auch einfach `cycle()` und `islice()` nehmen. Die Funktionen in `itertools` sind ja genau dafür gemacht das man die benutzen und kombinieren kann/soll, um das Rad nicht immer wieder neu zu erfinden, und dann nicht ganz rund sondern mit Ecken und Kanten und wenn man Pech hat auch mit Sollbruchstellen. `cycle()` kann zudem nicht nur mit Sequenztypen, sondern mit allen iterierbaren Objekten.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sorry aber dies kann ich nicht nachvollziehen, du weißt was ein Generator ist?__blackjack__ hat geschrieben: ↑Sonntag 1. Juli 2018, 19:19 @ThomasL: Bei Deiner Lösung stört, dass die Liste auch in den Fällen komplett durchlaufen wird wo gar nicht alle Elemente benötigt werden.
Bei jedem Abruf durch next() oder bei for item in wird EIN Element zurück gegeben.
Wenn ich keine Elemente abrufe wird auch nichts durchlaufen
Was ist denn das für nen Quatsch.Wenn man 1000 Elemente übergibt und 1005 haben möchte
Wenn man 1005 Elemente haben möchte, dann übergibt man den Wert 1005 und nicht 1000.
Und es werden auch keine 1000 Elemente übergeben. Hast du die Generatorfunktion my_generator überhaupt verstanden?
Der Funktion wird die Liste deren einzelne Elemente nacheinander und nach kompletten Durchlauf wieder von vorne an
ausgegeben werden sollen und die Anzahl der Elemente die maximale ausgegeben werden sollen, übergeben.
auch diesen Murks musst du mir mal genauer erklären.wird die ``for``-Schleife *in* der Funktion 2000 mal durchlaufen. Das sind 1995 mal mehr als nötig wären.
Die for-Schleife iteriert über die Elemente der übergebenen Liste, und mehr nicht.
Lass diesen Code hier laufen und dann überlege dir eine Erklärung
Code: Alles auswählen
def my_generator(my_list, count):
counter = count + 1
while counter > 0:
print(f'Counter:{counter}') # eingefügt
for item in my_list:
counter -= 1
if counter > 0:
yield item
output = my_generator([1,2,3,4,5,6,7,8,9,10,11,12], 1000)
for item in output:
print(f'Item:{item}')
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
- __blackjack__
- User
- Beiträge: 13110
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@ThomasL: Ja, ich weiss was ein Generator ist. Natürlich wird nichts durchlaufen wenn man keine Elemente abfragt, aber es werden ja Elemente abgefragt, sonst wäre es sinnlos den Generator zu erstellen.
Wieso ist es Quatsch 1000 Elemente zu übergeben und 1005 zurückbekommen zu wollen? Genau darum geht es doch. Original halt nicht 1000 und 1005 sondern es werden 12 Elemente übergenen und man möchte 1000 haben. Also statt ``my_generator(range(12), 1000)`` im Original war mein Beispiel ``my_generator(range(1000), 1005)``.
Den Code muss ich nicht laufen lassen und auch keine Erklärung finden, denn bei *der* Ausgabe sieht man das Problem nicht, denn die zeigt *nicht* wie oft die ``for``-Schleife durchlaufen wird. Wenn der Code das zeigen würde, dann hättest Du das Problem ja verstanden und würdest nicht mit Worten wie Murks und Quatsch in *meine* Richtung werfen.
Lass *Du* doch mal *das* hier laufen, wo in jedem Durchlauf der ``for``-Schleife ein Sternchen ausgegeben wird, und erkläre mir warum da 10 statt 6 Sternchen ausgegeben werden. Bei meinem Beispiel wären es dann 2000 statt 1005.
Ausgabe:
Da sind am Ende mindestens drei Sternchen zu viel.
Wieso ist es Quatsch 1000 Elemente zu übergeben und 1005 zurückbekommen zu wollen? Genau darum geht es doch. Original halt nicht 1000 und 1005 sondern es werden 12 Elemente übergenen und man möchte 1000 haben. Also statt ``my_generator(range(12), 1000)`` im Original war mein Beispiel ``my_generator(range(1000), 1005)``.
Den Code muss ich nicht laufen lassen und auch keine Erklärung finden, denn bei *der* Ausgabe sieht man das Problem nicht, denn die zeigt *nicht* wie oft die ``for``-Schleife durchlaufen wird. Wenn der Code das zeigen würde, dann hättest Du das Problem ja verstanden und würdest nicht mit Worten wie Murks und Quatsch in *meine* Richtung werfen.
Lass *Du* doch mal *das* hier laufen, wo in jedem Durchlauf der ``for``-Schleife ein Sternchen ausgegeben wird, und erkläre mir warum da 10 statt 6 Sternchen ausgegeben werden. Bei meinem Beispiel wären es dann 2000 statt 1005.
Code: Alles auswählen
def my_generator(my_list, count):
counter = count + 1
while counter > 0:
for item in my_list:
print('*') # eingefügt
counter -= 1
if counter > 0:
yield item
for item in my_generator(range(5), 6):
print(item)
Code: Alles auswählen
*
0
*
1
*
2
*
3
*
4
*
0
*
*
*
*
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Mit diesem Beispiel habe ich verstanden, was du gemeint hast.__blackjack__ hat geschrieben: ↑Sonntag 1. Juli 2018, 20:06 Wieso ist es Quatsch 1000 Elemente zu übergeben und 1005 zurückbekommen zu wollen?
Also statt ``my_generator(range(12), 1000)`` im Original war mein Beispiel ``my_generator(range(1000), 1005)``.
Ich hatte es so missverstanden, das my_generator(liste, 1000) erzeugt wird und dann 1005 Elemente ausgegeben werden sollen
Stimmt, ich nehme das Murks und Quatsch peinlich berührt zurück und entschuldige mich.Den Code muss ich nicht laufen lassen und auch keine Erklärung finden, denn bei *der* Ausgabe sieht man das Problem nicht, denn die zeigt *nicht* wie oft die ``for``-Schleife durchlaufen wird. Wenn der Code das zeigen würde, dann hättest Du das Problem ja verstanden und würdest nicht mit Worten wie Murks und Quatsch in *meine* Richtung werfen.
Da war ich ja wohl komplett auf dem Holzweg.
weil das hier gefehlt hatund erkläre mir warum da 10 statt 6 Sternchen ausgegeben werden. Bei meinem Beispiel wären es dann 2000 statt 1005.
Code: Alles auswählen
if counter > 0:
yield item
else:
break
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
Ich bin gerade dabei meine Übungsprojekte zu optimieren.__blackjack__ hat geschrieben: ↑Sonntag 1. Juli 2018, 17:12Code: Alles auswählen
In [174]: l = [1,2,3] In [175]: list(islice(cycle(l), 5)) Out[175]: [1, 2, 3, 1, 2]
Anstatt eine lange Liste mit Zahlen zu erzeugen und zu speichern, wollte ich dafür einen Generator verwenden.
Allerdings ist mir nicht so ganz klar, ob die Funktionen `cycle` und `islice` aus dem Modul `itertools` bereits wie ein Generator funktionieren.
Gruß
Atalanttore
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
Mit folgendem Code, erstellt mit Unterstützung von Stack Overflow, habe ich festgestellt, dass es kein Generator ist.
Gruß
Atalanttore
Code: Alles auswählen
from itertools import islice, cycle
import types
l = [1,2,3]
print(isinstance(list(islice(cycle(l), 5)), types.GeneratorType))
Atalanttore
Du wandelst das islice-Objekt ja auch in eine Liste um. Ein Generator ist auch nur eine von vielen Möglichkeiten von einem iterierbaren Objekt. Da islice in C implementiert ist, ist es kein Generator.
Bei `cycle` ist eigentlich klar, dass es nicht wie eine Liste ist, weil es unendlich viele Elemente enthält.
Bei `cycle` ist eigentlich klar, dass es nicht wie eine Liste ist, weil es unendlich viele Elemente enthält.
-
- User
- Beiträge: 407
- Registriert: Freitag 6. August 2010, 17:03
Ich habe das Beispiel erweitert und die Umwandlung in eine Liste entfernt.
Code: Alles auswählen
from itertools import islice, cycle
import types
numbers = [1,2,3,4,5,6,7,8,9,10]
def liste(l):
number = islice(cycle(l), 25)
yield number
for i in range(10):
print(next(liste(numbers)))
print(isinstance(liste(numbers), types.GeneratorType))
Warum ist das so?
Soweit ich es jetzt verstanden habe, wiederholt `cycle()` die Elemente in der übergebenen Liste wieder und wieder. `islice()` sorgt dann dafür, dass bei der übergebenen Anzahl an Elementen Schluss ist.
Gruß
Atalanttore