Zip-Iteratoren, die in Python die gleiche Länge behauptenPython

Python-Programme
Anonymous
 Zip-Iteratoren, die in Python die gleiche Länge behaupten

Post by Anonymous »

Ich suche nach einer guten Möglichkeit, mehrere Iterables zu komprimieren und eine Ausnahme auszulösen, wenn die Längen der Iterables nicht gleich sind.
Für den Fall, dass die Iterables Listen sind oder eine len-Methode haben, ist diese Lösung sauber und einfach:

Code: Select all

def zip_equal(it1, it2):
if len(it1) != len(it2):
raise ValueError("Lengths of iterables are different")
return zip(it1, it2)
Wenn it1 und it2 jedoch Generatoren sind, schlägt die vorherige Funktion fehl, weil die Länge nicht definiert ist. TypeError: Objekt vom Typ „Generator“ hat kein len().
Ich stelle mir vor, dass das Modul itertools eine einfache Möglichkeit bietet, das zu implementieren, aber bisher konnte ich es nicht finden. Ich habe mir diese hausgemachte Lösung ausgedacht:

Code: Select all

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
Die Lösung kann mit dem folgenden Code getestet werden:

Code: Select all

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)
Übersehe ich eine alternative Lösung? Gibt es eine einfachere Implementierung meiner zip_equal-Funktion?
Update:
  • Python 3.10 oder neuer erforderlich, siehe Antwort von sahinakkaya
  • Gründliches Leistungsbenchmarking und leistungsstärkste Lösung auf Python

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post