Zip-итераторы, утверждающие одинаковую длину в PythonPython

Программы на Python
Ответить
Anonymous
 Zip-итераторы, утверждающие одинаковую длину в Python

Сообщение Anonymous »

Я ищу хороший способ заархивировать несколько итераций, вызывающих исключение, если длины итераций не равны.
В случае, когда итерации представляют собой списки или имеют метод len, это решение простое и понятное:

Код: Выделить всё

def zip_equal(it1, it2):
if len(it1) != len(it2):
raise ValueError("Lengths of iterables are different")
return zip(it1, it2)
Однако, если it1 и it2 являются генераторами, предыдущая функция завершается с ошибкой, поскольку длина не определена. TypeError: объект типа 'generator' не имеет len().
Я предполагаю, что модуль itertools предлагает простой способ реализовать это, но до сих пор мне не удалось его найти. Я придумал вот такое самодельное решение:

Код: Выделить всё

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
Решение можно протестировать с помощью следующего кода:

Код: Выделить всё

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)
Не упускаю ли я какое-либо альтернативное решение? Есть ли более простая реализация моей функции zip_equal?
Обновление:
  • Требуется Python 3.10 или новее, см. ответ Сахинаккая.
  • Тщательное тестирование производительности и наиболее эффективное решение на Python

    Подробнее здесь: https://stackoverflow.com/questions/329 ... -in-python
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»