gpt4 book ai didi

python - 有没有更好的方法在 python 中执行 "unravel"函数?

转载 作者:太空宇宙 更新时间:2023-11-03 13:17:16 25 4
gpt4 key购买 nike

我遇到了执行 n 个并发事件的问题,这些事件都将迭代器返回到它们获取的结果。但是,有一个可选的 limit 参数表示,基本上,合并所有迭代器并返回最多 limit 结果。

因此,例如:我在 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,3,5,7]
>>> d = [2,4,6,8]
>>>
>>> print([e for e in unravel(c, d)])
[1, 2, 3, 4, 5, 6, 7, 8]
>>> print([e for e in unravel(c, d, with_limit = 3)])
[1, 2, 3]
>>> print([e for e in unravel(a, b, with_limit = 6)])
[1, 6, 2, 7, 3, 8]
>>> print([e for e in unravel(a, b, with_limit = 100)])
[1, 6, 2, 7, 3, 8, 4, 9, 5, 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, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9]
>>> print(list(unravel(a, b, limit = 3)))
[1, 1, 2]
>>> print(list(unravel(a, b, c, d, limit = 20)))
[1, 1, 1, 2, 3, 2, 2, 4, 5, 3, 3, 6, 7, 4, 4, 8, 9, 5, 10, 11]

最佳答案

您在这里所做的几乎只是zip

您想要一个平面可迭代对象,而不是子可迭代对象的可迭代对象,但是 chain 解决了这个问题。

您只想获取前 N 个值,但是 islice 解决了这个问题。

所以,如果长度都相等:

>>> list(chain.from_iterable(zip(a, b)))
[1, 6, 2, 7, 3, 8, 4, 9, 5, 10]
>>> list(islice(chain.from_iterable(zip(a, b)), 7))
[1, 6, 2, 7, 3, 8, 4]

但是如果长度不相等,它将在第一个可迭代完成后立即停止,这是您不希望的。 stdlib 中唯一的选择是 zip_longest,它用 None 填充缺失值。

您可以很容易地编写一个 zip_longest_skipping(这实际上是 Peter 的回答中的 round_robin),但您也可以只使用 zip_longest 和过滤器出结果:

>>> list(filter(None, chain.from_iterable(zip_longest(a, b, c, d))))
[1, 6, 1, 2, 2, 7, 3, 4, 3, 8, 5, 6, 4, 9, 7, 8, 5, 10]

(显然,如果您的值全部是字符串或 None,这将无法正常工作,但是当它们都是正整数时,它可以正常工作……处理“或 None "的情况下,执行 sentinel=object(),将其传递给 zip_longest,然后过滤 x is not sentinel。)

关于python - 有没有更好的方法在 python 中执行 "unravel"函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25069497/

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