python - zip_longest 没有填充值

标签 python functional-programming python-itertools

我正在寻找 Python 的 zipzip_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 来改进吗?哪种方法似乎最有效?

最佳答案

zipzip_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_passiters 中删除完成的迭代器可能更有效 函数如下:

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/

相关文章:

python - 如何指定只允许某些第一个组合的 itertools 排列?

python - Numpy 和 Pandas 之间有性能差异吗?

python - 如何使 python 对象 json 序列化?

python - 获取张量 a 中存在于张量 b 中的元素的索引

python - 如何编写迭代器?

javascript - 在 JavaScript 的括号语句中是否有一个 "while"等价物?

javascript - 干刮点击 "load more button"

clojure - 为什么 Clojure 在创建新的命名空间后不提供标准库?

python - 按键分组字典并找到最大值

python - 用零填充 3D 列表中的缺失值以创建 3D numpy 数组