2014-11-21 3 views
5

Ho una lista di funzioni di generatore come:scarico una lista di generatori in modo ciclico

def myGen(x): 
    for i in range(x): 
     yield i 
g5 = myGen(5); g10 = myGen(10); g15 = myGen(15) 
cycleList = [g5, g10, g15] 

Qual è il modo migliore per passare tra questi generatori e rimuovere quelli che sono esauriti dalla lista?

L'output dovrebbe essere:

0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 6 6 7 7 8 8 9 9 10 11 12 13 14 

risposta

5

Sembra che si desidera che il roundrobinitertools recipe:

def roundrobin(*iterables): 
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C" 
    # Recipe credited to George Sakkis 
    pending = len(iterables) 
    nexts = cycle(iter(it).next for it in iterables) 
    while pending: 
     try: 
      for next in nexts: 
       yield next() 
     except StopIteration: 
      pending -= 1 
      nexts = cycle(islice(nexts, pending)) 

In uso:

>>> from itertools import cycle, islice 
>>> for i in roundrobin(xrange(5), xrange(10), xrange(15)): 
    print i, 


0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 6 6 7 7 8 8 9 9 10 11 12 13 14 
2

la ricetta round robin è un modo migliore per andare ma potresti anche usare chainizip_longest e ifilterfalse:

from itertools import chain, izip_longest, ifilterfalse 
for x in ifilterfalse(lambda x: x is None,chain.from_iterable(izip_longest(*cycleList))): 
     print x, 
0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 6 6 7 7 8 8 9 9 10 11 12 13 14 

Se si può avere Nessuno come oggetto l'uso di valore:

my_object = object 
for x in ifilterfalse(lambda x: x is my_object,chain.from_iterable(izip_longest(*cycleList,fillvalue=my_object))): 
     print x,