2015-06-12 14 views
7

data una lista di coppie xys, l'idioma Python per decomprimere in due liste è:Come decomprimere un iteratore?

xs, ys = zip(*xys) 

Se xys è un iteratore, come posso decomprimerlo in due iteratori, senza memorizzare tutto nella memoria?

+0

_ "Dato un elenco di coppie xys" _ Quindi qualcosa come '[(1,2), (2,3), (3,4), ...]'? Non è necessario comprimerlo; è già lista (o iteratore) di tuple. –

+1

Voglio convertire xys in due iteratori separati xs = [1,2,3, ...] e ys = [2,3,4, ...] –

+0

Quindi xys è qualcosa come '[[1,2, 3], [2,3,4]] '? Allora "itertools.izip" è quello che vuoi. Questa è una coppia di liste, non una lista di coppie. –

risposta

4

Supponiamo di avere un po 'di iterabile di coppie:

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

Se sto correttamente interpretare ciò che si sta chiedendo, si potrebbe generare iteratori indipendenti per i primi e secondi con itertools.tee:

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

Nota: ciò manterrà in memoria la "differenza" tra quanto si itera uno di essi rispetto all'altro.

6

Se si desidera consumare un iteratore indipendentemente dall'altro, non c'è modo di evitare di trascinare oggetti in memoria, poiché uno degli iteratori progredirà mentre l'altro non lo fa (e quindi deve bufferizzare).

Qualcosa del genere consente di eseguire iterazioni su entrambi i 'oggetti lasciati' e le 'voci giuste' delle coppie:

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)) 

... ma di tenere presente che se si consumano solo un iteratore, l'altro memorizzerà gli elementi in memoria fino a quando non inizierai a consumarli.

(Btw, assumendo Python 3. In Python 2 è necessario utilizzare itertools.imap(), non map().)

+1

In effetti [i documenti] (https://docs.python.org/2/library/itertools.html#itertools.tee) hanno un avvertimento su questo: * "Questo itertoolo potrebbe richiedere una memoria ausiliaria significativa (a seconda di quanto tempo i dati devono essere memorizzati). In generale, se un iteratore utilizza la maggior parte o tutti i dati prima che inizi un altro iteratore, è più veloce usare 'list()' invece di 'tee()'. "* – jonrsharpe