Sto cercando un modo semplice per zip
diversi iterabili che generano un'eccezione se le lunghezze dei iterabili non sono uguali.iteratori zip che affermano per uguale lunghezza in python
Nel caso in cui i iterabili sono elenchi o avere un metodo len
questa soluzione è pulito e facile:
def zip_equal(it1, it2):
if len(it1) != len(it2):
raise ValueError("Lengths of iterables are different")
return zip(it1, it2)
Tuttavia, se it1
e it2
sono generatori, la funzione precedente non riesce perché la lunghezza non è definita TypeError: object of type 'generator' has no len()
.
Immagino che il modulo itertools
offra un modo semplice per implementarlo, ma finora non sono stato in grado di trovarlo. Sono venuto su con questa soluzione fatta in casa:
def zip_equal(it1, it2):
exhausted = False
while True:
try:
el1 = next(it1)
if exhausted: # in a previous iteration it2 was exhausted but it1 still has elements
raise ValueError("it1 and it2 have different lengths")
except StopIteration:
exhausted = True
# it2 must be exhausted too.
try:
el2 = next(it2)
# here it2 is not exhausted.
if exhausted: # it1 was exhausted => raise
raise ValueError("it1 and it2 have different lengths")
except StopIteration:
# here it2 is exhausted
if not exhausted:
# but it1 was not exhausted => raise
raise ValueError("it1 and it2 have different lengths")
exhausted = True
if not exhausted:
yield (el1, el2)
else:
return
La soluzione può essere testato con il seguente codice:
it1 = (x for x in ['a', 'b', 'c']) # it1 has length 3
it2 = (x for x in [0, 1, 2, 3]) # it2 has length 4
list(zip_equal(it1, it2)) # len(it1) < len(it2) => raise
it1 = (x for x in ['a', 'b', 'c']) # it1 has length 3
it2 = (x for x in [0, 1, 2, 3]) # it2 has length 4
list(zip_equal(it2, it1)) # len(it2) > len(it1) => raise
it1 = (x for x in ['a', 'b', 'c', 'd']) # it1 has length 4
it2 = (x for x in [0, 1, 2, 3]) # it2 has length 4
list(zip_equal(it1, it2)) # like zip (or izip in python2)
Perchè sono affacciate qualsiasi soluzione alternativa? Esiste un'implementazione più semplice della mia funzione zip_equal
?
PS: Ho scritto la domanda pensando in Python 3, ma una soluzione Python 2 è anche benvenuta.
La soluzione 'resa from' è molto bello. Grazie per quello e per fornire due soluzioni diverse. – colidyre
Grazie! A proposito, in 'zip_longest' l'argomento' fill_value' dovrebbe essere 'fillvalue' ;-). – zeehio
@zeehio: Oops, corretto. –