Seite 1 von 1
Die ersten x Elemente eines Generators abrufen. Geht das?
Verfasst: Dienstag 19. Oktober 2010, 08:29
von mutetella
Hallo,
gibt es für
außer
noch andere Möglichkeiten, die ersten Elemente eines Generators abzurufen. Vielleicht eine Built-in Funktion, die ich nicht kenne...
Oder ist islice() für sowas ok?
Re: Die ersten x Elemente eines Generators abrufen. Geht das
Verfasst: Dienstag 19. Oktober 2010, 08:37
von Xynon1
mir fällt spontan nur
ein.
Zerstört natürlich die Vorteile des generators.
Re: Die ersten x Elemente eines Generators abrufen. Geht das
Verfasst: Dienstag 19. Oktober 2010, 08:42
von mutetella
Xynon1 hat geschrieben:Zerstört natürlich die Vorteile des generators.
Und ist auf einen "unendlichen" Generator nicht anwendbar, da hierbei ja erstmal alle Elemente des Generators durchlaufen werden.
Re: Die ersten x Elemente eines Generators abrufen. Geht das
Verfasst: Dienstag 19. Oktober 2010, 08:47
von Xynon1
richtig, danke für den Hinweis, hatte ich übersehen.
Re: Die ersten x Elemente eines Generators abrufen. Geht das
Verfasst: Dienstag 19. Oktober 2010, 08:55
von BlackJack
Aber man kann daraus trotzdem etwas verwenden: ``list(islice(generator, 5))``
Re: Die ersten x Elemente eines Generators abrufen. Geht das
Verfasst: Dienstag 19. Oktober 2010, 08:55
von cofi
Nuja, du kannst auch direkt mit `islice` auf den Generator zugreifen oder benoetigst du unbedingt die Liste? Daneben koenntest du einfach ueber `enumerate(generator)` iterieren und bei 5 abbrechen.
Viele Moeglichkeiten. Wenn du vielleicht noch was zum Kontext sagst kann man dir bestimmt konkreter helfen.
Re: Die ersten x Elemente eines Generators abrufen. Geht das
Verfasst: Dienstag 19. Oktober 2010, 09:20
von mutetella
cofi hat geschrieben:Wenn du vielleicht noch was zum Kontext sagst kann man dir bestimmt konkreter helfen.
Es geht darum, Wiederholungen eines Termins zu begrenzen, z. B. 'Diesen Termin alle 2 Tage bis zum 14. Dezember 2010 wiederholen.' Soweit kein Problem, das end_date ist hier ja bereits bekannt. Sofern allerdings nur bekannt ist, dass die 2tägige Wiederholung 5 x stattfinden soll, braucht es eine Methode, das end_date zu ermitteln.
Ich habe dafür eine Methode 'recurrence_list()' gebastelt, die mir eine bestimmte Anzahl von passenden Wiederholungen zurückgibt. In diesem Fall bedeutet passend, dass die date's, ausgehend vom start_date jeweils 2 Tage auseinanderliegen, nicht in exceptions enthalten sind und sich innerhalb start_date und end_date (das, wenn noch nicht bekannt, datetime.date(9999, 12, 31) ist) befinden.
Code: Alles auswählen
from datetime import date as Date, timedelta as TimeDelta
from itertools import ifilter, islice
MAX_DATE = Date.max
class Recurrence(object):
def __init__(self, start_date, end_date=MAX_DATE, \
count=None, exceptions=[]):
self.start_date = start_date
self.end_date = end_date
self.count = count
self.exceptions = set(exceptions)
if count is not None:
self.end_date = self.recurrence_list(count)[-1]
def recurrence_list(self, count, date=None,):
if date is None:
date = self.start_date
count = count * self.recurrence_len
return [elements for elements in islice(self._iter_check(), count)]
def _basic_check(self, date):
return self._exceptions_check(date) \
and self._range_check(date)
def _exceptions_check(self, date):
return date not in self.exceptions
def _range_check(self, date):
return self.start_date < date <= self.end_date
def _iter_check(self, start_date=None, end_date=None):
if start_date is None:
start_date = self.start_date
if end_date is None:
end_date = self.end_date
return ifilter(self.check, iter_dates(self.start_date,
self.end_date))
class DailyRecurrence(Recurrence):
def __init__(self, start_date, interval, \
end_date=MAX_DATE, count=None, exceptions=[]):
self.interval = interval
self.recurrence_len = 1
Recurrence.__init__(self, start_date, end_date, count, exceptions)
def check(self, date):
return self._basic_check(date) \
and self._check_interval(date)
def _check_interval(self, date):
day_distance = (date - self.start_date).days
return day_distance % self.interval == 0
def iter_dates(start_date, end_date):
next = TimeDelta(days=1)
while start_date <= end_date:
yield start_date
start_date += next
Der Aufruf sieht dann so aus:
Code: Alles auswählen
In [239]: d = calendar.DailyRecurrence(datetime.date(2010,10,1), 2, count=5)
In [240]: d.end_date
Out[240]: datetime.date(2010, 10, 11)
Re: Die ersten x Elemente eines Generators abrufen. Geht das
Verfasst: Dienstag 19. Oktober 2010, 09:30
von cofi
In dem Fall brauchst du dann die Liste - sofern du den Aufruf nicht aenderst, haette da jetzt aber auch keine sinnvolle Idee -, allerdings wuerde ich da BlackJacks Vorschlag vorziehen.
Anstatt den `_*_check` wuerde ich Namen der Art `_is_*` bzw `_in_*` vorschlagen, dann sieht man auch gleich den Sinn des Tests.
Re: Die ersten x Elemente eines Generators abrufen. Geht das
Verfasst: Dienstag 19. Oktober 2010, 10:16
von mutetella
cofi hat geschrieben:...allerdings wuerde ich da BlackJacks Vorschlag vorziehen.
Warum?
cofi hat geschrieben:Anstatt den `_*_check` wuerde ich Namen der Art `_is_*` bzw `_in_*` vorschlagen, ...
Ok, macht Sinn, werd' ich ändern.
Re: Die ersten x Elemente eines Generators abrufen. Geht das
Verfasst: Dienstag 19. Oktober 2010, 10:49
von cofi
Code: Alles auswählen
[elements for elements in islice(self._iter_check(), count)]
finde ich gegenueber
zu schwalig, v.a. geht die Itention da etwas unter. Wenn du doch daran festhaelst, wuerde ich aber `elements` zu `element` machen
