我正在寻找 Python 的 zip
和 zip_longest
函数(来自 itertools 模块)之间的中间地带,它会耗尽所有给定的迭代器,但不填写任何内容。因此,例如,它应该像这样转置元组:
(11, 12, 13 ), (11, 21, 31, 41),
(21, 22, 23, 24), --> (12, 22, 32, 42),
(31, 32 ), (13, 23, 43),
(41, 42, 43, 44), ( 24, 44)
(添加空格是为了更好地对齐图形。)
我通过清除 zip_longest
之后的 fillvalue
设法组成了一个粗略的解决方案。
def zip_discard(*iterables, sentinel = object()):
return map(
partial(filter, partial(is_not, sentinel)),
zip_longest(*iterables, fillvalue=sentinel))
有没有办法在不引入哨兵的情况下做到这一点?这可以使用 yield
来改进吗?哪种方法似乎最有效?
最佳答案
zip
和 zip_longest
都被设计成总是生成等长的元组,你可以定义你自己的生成器,它不关心 len,像这样:
def _one_pass(iters):
for it in iters:
try:
yield next(it)
except StopIteration:
pass #of some of them are already exhausted then ignore it.
def zip_varlen(*iterables):
iters = [iter(it) for it in iterables]
while True: #broken when an empty tuple is given by _one_pass
val = tuple(_one_pass(iters))
if val:
yield val
else:
break
如果压缩在一起的数据相当大,那么每次都跳过耗尽的迭代器可能会很昂贵,从 _one_pass中的
函数如下:iters
中删除完成的迭代器可能更有效
def _one_pass(iters):
i = 0
while i<len(iters):
try:
yield next(iters[i])
except StopIteration:
del iters[i]
else:
i+=1
这两个版本都不需要创建中间结果或使用临时填充值。
关于python - zip_longest 没有填充值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38054593/