2015-06-12 19 views
7

Biorąc pod uwagę listę par xys, idiom Python rozpakować go do dwóch list jest:Jak rozpakować Iterator?

xs, ys = zip(*xys) 

Jeśli xys jest iterator, jak mogę rozpakować go na dwa iteratory, bez zapisywania wszystkiego w pamięci?

+0

_ "Biorąc pod uwagę listę par xys" _ Tak coś jak "[(1,2), (2,3), (3,4), ...]"? Nie musisz tego zamykać; to już lista (lub iterator) krotek. –

+1

Chcę przekonwertować xys na dwa oddzielne iteratory xs = [1,2,3, ...] i ys = [2,3,4, ...] –

+0

Więc xys jest coś w stylu '[[1,2, 3], [2,3,4]] "? Wtedy 'itertools.izip' jest tym, czego potrzebujesz. To para list, a nie lista par. –

Odpowiedz

4

Załóżmy, że masz jakieś iterowalny par:

a = zip(range(10), range(10)) 

Jeśli mam poprawnie interpretując co prosicie, można generować niezależnych iteratorów dla nowatorskich rozwiązań i sekund używając itertools.tee:

xs, ys = itertools.tee(a) 
xs, ys = (x[0] for x in xs), (y[1] for y in ys) 

Notatka to zapisze w pamięci "różnicę" między tym, jak jeden z nich się sprawdza w stosunku do drugiego.

6

Jeśli chcesz spożywać jeden iterator niezależnie od drugiego, nie ma sposobu, aby uniknąć wciągnięcia rzeczy do pamięci, ponieważ jeden z iteratorów będzie się rozwijał, podczas gdy drugi nie będzie (a zatem musi buforować).

Coś takiego pozwala iterować zarówno „rzeczy pozostawione” i „prawych pozycji” par:

import itertools 
import operator 

it1, it2 = itertools.tee(xys) 
xs = map(operator.itemgetter(0), it1)) 
ys = map(operator.itemgetter(1), it2)) 

print(next(xs)) 
print(next(ys)) 

... ale należy pamiętać, że jeśli zużywają tylko jedną iterację, drugi buforuje elementy w pamięci, dopóki ich nie zużyjesz.

(Btw, zakładając Python 3. W Pythonie 2 trzeba użyć itertools.imap(), nie map().)

+1

Rzeczywiście [the docs] (https://docs.python.org/2/library/itertools.html#itertools.tee) mają ostrzeżenie w tej sprawie: * "To itertool może wymagać znacznej pamięci dyskowej (w zależności od tego, ile tymczasowego dane muszą być przechowywane) .Jeśli jeden iterator używa większości lub wszystkich danych przed uruchomieniem innego iteratora, szybciej jest użyć 'list()' zamiast 'tee()'. "* – jonrsharpe