2012-07-16 11 views
8

Chciałbym wiedzieć, jak napisać funkcję Pythona, która może spłaszczyć generator, który daje inne generatory lub iteables (które mogą również przynieść inne generatory/iterables ... ewentualnie nieskończenie).Python: Funkcja spłaszczania generatora zawierającego inny generator

Oto przykład:

gen(gen(1,2,3), gen(4,5,6), [7,8,9], [gen(10,11,12), gen(13,14,15)])

uwaga: gen - środki generatora obiektu, zawartość w nawiasach po gen to dane będą generatora gen wydajność.

Oczekiwany wynik po „spłaszczenie”: gen(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)

Konieczne jest funkcja Spłaszczenie powrót generator też! (ponieważ w przeciwnym razie wcześniejsze użycie generatorów byłoby bez znaczenia).

Proszę zauważyć, że używam python 3.

Dzięki!

Odpowiedz

12

Najprostszym sposobem jest rekurencyjna funkcja spłaszczania. Zakładając, że chcesz zejść na każdym iterable wyjątkiem ciągów, można to zrobić:

def flatten(it): 
    for x in it: 
     if (isinstance(x, collections.Iterable) and 
      not isinstance(x, str)): 
      for y in flatten(x): 
       yield y 
     else: 
      yield x 

Począwszy od Pythona 3.3, można również napisać

def flatten(it): 
    for x in it: 
     if (isinstance(x, collections.Iterable) and 
      not isinstance(x, str)): 
      yield from flatten(x) 
     else: 
      yield x 
+0

Dziękuję bardzo! Z moją próbą byłem bardzo blisko twoich :-) Pozdrawiam! – JoshuaBoshi

+0

+1 - Ciągle zapominam o "wydajności od" i to było miłe przypomnienie. –

+2

@JonClements: "Nie zapominaj" o funkcjach wersji Pythona, która jeszcze nie została wydana? Jestem zaskoczony. :) –

0

Sposób nierekursywnych jest zasadniczo rozwijanie wśród metoda rekursywna, przy użyciu stosu:

def flatten(it): 
    stack = [] 
    it = iter(it) 
    while True: 
     try: 
      x = next(it) 
     except StopIteration: 
      if stack: 
       it = stack.pop() 
       continue 
      else: 
       return 
     if isinstance(x, collections.Iterable) and not isinstance(x, str): 
      stack.append(it) 
      it = iter(x) 
     else: 
      yield x 
Powiązane problemy