有没有更好的方法在python中执行“解开”功能?
我遇到了执行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上过滤不是哨兵.) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |