在 python 中并行迭代单个列表

iterating over a single list in parallel in python

objective是在并行中使用builtin[=51=对单个iter进行计算] sum & map 函数 同时 。也许使用(类似于)itertools 而不是经典的 for loops 来分析通过 iterator...

到达的(大)数据

在一个简单的 示例中 我想计算 ilen, sum_x & sum_x_sq:

ilen,sum_x,sum_x_sq=iterlen(iter),sum(iter),sum(map(lambda x:x*x, iter))

但没有将 (大) iter 转换为 list(与 iter=list(iter) 一样)

n.b。使用 sum & map 且不使用 for loops,也许使用 itertools and/or threading 模块?

def example_large_data(n=100000000, mean=0, std_dev=1):
  for i in range(n): yield random.gauss(mean,std_dev)

-- 编辑--

非常具体:我仔细研究了 itertools,希望有像 map 这样的双重功能可以做到这一点。例如:len_x,sum_x,sum_x_sq=itertools.iterfork(iter_x,iterlen,sum,sum_sq)

如果我要非常非常具体:我正在寻找一个答案,python“iterfork”程序的源代码。

您可以使用 itertools.tee 将您的单个迭代器变成三个迭代器,您可以将其传递给您的三个函数。

iter0, iter1, iter2 = itertools.tee(input_iter, 3)
ilen, sum_x, sum_x_sq = count(iter0),sum(iter1),sum(map(lambda x:x*x, iter2))

工作,但是内置函数 sum (和 Python 2 中的 map )没有以这样的方式实现支持并行迭代。您调用的第一个函数将完全使用它的迭代器,然后第二个函数将使用第二个迭代器,然后第三个函数将使用第三个迭代器。由于 tee 必须存储其输出迭代器之一而不是所有其他迭代器看到的值,这与从迭代器创建列表并将其传递给每个函数本质上相同。

现在,如果您使用的生成器函数对于它们输出的每个值仅从输入中消耗一个值,您也许可以使用 zip 进行并行迭代。在Python 3中,mapzip都是生成器。问题是如何将 sum 变成生成器。

我认为您可以通过使用 itertools.accumulate(在 Python 3.2 中添加)获得您想要的东西。它是一个产生 运行 输入总和的生成器。以下是如何让它解决您的问题(我假设您的 count 函数应该是 len 的迭代器友好版本):

iter0, iter1, iter2 = itertools.tee(input_iter, 3)

len_gen = itertools.accumulate(map(lambda x: 1, iter0))
sum_gen = itertools.accumulate(iter1)
sum_sq_gen = itertools.accumulate(map(lambda x: x*x, iter2))

parallel_gen = zip(len_gen, sum_gen, sum_sq_gen)  # zip is a generator in Python 3

for ilen, sum_x, sum_x_sq in parallel_gen:
    pass    # the generators do all the work, so there's nothing for us to do here

# ilen_x, sum_x, sum_x_sq have the right values here!

如果您使用的是 Python 2 而不是 3,则您必须编写自己的 accumulate 生成器函数(在我的文档中有一个纯粹的 Python 实现上面链接),并使用 itertools.imapitertools.izip 而不是内置的 mapzip 函数。