gpt4 book ai didi

python - zip迭代器在python中断言相等的长度

转载 作者:IT老高 更新时间:2023-10-28 21:11:47 24 4
gpt4 key购买 nike

我正在寻找一种很好的方法来 zip 几个迭代器,如果迭代器的长度不相等,则会引发异常。

在可迭代对象是列表或具有 len 方法的情况下,此解决方案简洁明了:

def zip_equal(it1, it2):
if len(it1) != len(it2):
raise ValueError("Lengths of iterables are different")
return zip(it1, it2)

但是,如果 it1it2 是生成器,则前面的函数会失败,因为未定义长度 TypeError: object of type 'generator' has no 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 或更高版本,请参阅 Asocia 的 answer
  • python<3.10 上的全面性能基准测试和最佳性能解决方案:Stefan 的 answer
  • 没有外部依赖的简单答案:Martijn Pieters 的 answer (请查看评论以获取某些极端情况下的错误修复)
  • 比 Martijn 的更复杂,但性能更好:cjerdonek 的 answer
  • 如果您不介意包依赖,请参阅pylang的answer

最佳答案

PEP 618 中的内置zip 函数引入了可选的 bool 关键字参数strict .

引用 What’s New In Python 3.10 :

The zip() function now has an optional strict flag, used to require that all the iterables have an equal length.

启用后,如果其中一个参数在其他参数之前用完,则会引发 ValueError

>>> list(zip('ab', range(3)))
[('a', 0), ('b', 1)]
>>> list(zip('ab', range(3), strict=True))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: zip() argument 2 is longer than argument 1

关于python - zip迭代器在python中断言相等的长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32954486/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com