加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

有没有更好的方法在python中执行“解开”功能?

发布时间:2020-12-20 11:36:50 所属栏目:Python 来源:网络整理
导读:我遇到了执行n个并发事件的问题,这些事件都将迭代器返回到他们获取的结果.但是,有一个可选的限制参数,基本上说,要整合所有迭代器并返回最多限制结果. 因此,例如:我在8个线程上执行2,000个url请求但只想要前100个结果,但不是所有100个来自同一个潜在线程. 因
我遇到了执行n个并发事件的问题,这些事件都将迭代器返回到他们获取的结果.但是,有一个可选的限制参数,基本上说,要整合所有迭代器并返回最多限制结果.

因此,例如:我在8个线程上执行2,000个url请求但只想要前100个结果,但不是所有100个来自同一个潜在线程.

因此,解开:

import itertools

def unravel(*iterables,with_limit = None):
    make_iter = {a:iter(i) for a,i in enumerate(iterables)}

    if not isinstance(with_limit,int):
        with_limit = -1

    resize = False

    while True:
        for iid,take_from in make_iter.items():
            if with_limit == 0:
                raise StopIteration

            try:
                yield next(take_from)
            except StopIteration:
                resize = iid
            else: 
                with_limit -= 1

        if resize:
            resize = False

            if len(make_iter.keys()) > 1:
                make_iter.pop(resize)

            else: raise StopIteration

用法:

>>> a = [1,2,3,4,5]
>>> b = [6,7,8,9,10]
>>> c = [1,5,7]
>>> d = [2,6,8]
>>> 
>>> print([e for e in unravel(c,d)])
[1,8]
>>> print([e for e in unravel(c,d,with_limit = 3)])
[1,3]
>>> print([e for e in unravel(a,b,with_limit = 6)])
[1,8]
>>> print([e for e in unravel(a,with_limit = 100)])
[1,10]

这样的事情是否已经存在,或者这是一个不错的实现?

谢谢

编辑,工作修复

受到@abernert建议的启发,这就是我的选择.谢谢大家!

def unravel(*iterables,limit = None):
    yield from itertools.islice(
            filter(None,itertools.chain.from_iterable(
                    itertools.zip_longest(
                        *iterables
                    )
                ) 
            ),limit)



>>> a = [x for x in range(10)]
>>> b = [x for x in range(5)]
>>> c = [x for x in range(0,20,2)]
>>> d = [x for x in range(1,30,2)]
>>> 
>>> print(list(unravel(a,b)))
[1,1,9]
>>> print(list(unravel(a,limit = 3)))
[1,2]
>>> print(list(unravel(a,c,limit = 20)))
[1,10,11]

解决方法

你在这里做的几乎就是拉链.

你想要一个可迭代的平面,而不是可迭代的子迭代,而是链修复.

并且您只想获取前N个值,但是islice修复了这个值.

所以,如果长度都相等:

>>> list(chain.from_iterable(zip(a,10]
>>> list(islice(chain.from_iterable(zip(a,b)),7))
[1,4]

但是如果长度不相等,那么只要第一个可迭代完成就会停止,这是你不想要的.而stdlib中唯一的替代方法是zip_longest,它使用None填充缺失值.

你可以很容易地编写一个zip_longest_skipping(这实际上是Peter的答案中的round_robin),但你也可以只是zip_longest并过滤掉结果:

>>> list(filter(None,chain.from_iterable(zip_longest(a,d))))
[1,10]

(显然如果你的值都是字符串或None都不行,但是当它们都是正整数时它工作正常……处理“或无”情况时,执行sentinel = object(),将其传递给zip_longest,然后在x上过滤不是哨兵.)

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读