在Python中从生成器获取多个单独的值

时间:2012-11-25 16:13:49

标签: python iterator generator itertools

如何从迭代器中的不同索引位置获取多个任意值?

How to get the n next values of a generator in a list (python)Get the nth item of a generator in Python描述了使用itertools.islice从迭代器中获取任意元素或连续子集。但是如果我想在迭代器中使用来自不同位置的多个任意元素,那么你不能只使用islice的步骤参数呢?

我正在尝试解决Project Euler的problem 40。我用

生成了一串连接的整数
iteration = (i for i in ''.join(map(str, (i for i in xrange(1,10**6)))))

现在我想从1开始获取索引1,10,100,1000,10000,100000,1000000的元素。我在这里无法使用islice,因为每次调用next将当前值转移到右边。例如

next(islice(iteration, 1, 2)) + next(islice(iteration, 3, 4))

产生'26'而不是'24'。

更新(25.11.12,4:43 UTC + 0)

感谢所有建议。我目前的代码如下:

it = (i for i in ''.join(map(str, (i for i in xrange(1,10**6)))))
ds = [int(nth(it, 10**i-10**(i-1)-1)) for i in range(7)]
return product(ds)

nth的丑陋论据是生成0,8,89,899,8999等序列。

3 个答案:

答案 0 :(得分:4)

(请注意,有更快的方法可以解决Euler#40。)

我的工作方式会有所不同。而不是使用nth

>>> from itertools import chain, count, islice
>>> 
>>> it = chain.from_iterable(str(i) for i in count(1))
>>> wanted = {10**i for i in range(7)}
>>> scan_region = islice(it, max(wanted)+1)
>>> digits = [int(x) for i, x in enumerate(scan_region, 1) if i in wanted]
>>> digits
[1, 1, 5, 3, 7, 2, 1]

这样我就不必做任何减法以确保我有正确的索引。

答案 1 :(得分:1)

这是the "recipes" section of the itertools documentation。它返回n的{​​{1}}元素,并按原样使用它:

iterable

你可以通过顺序调用它来获取第1个,第10个,第100个等元素(注意迭代器被消耗,并且是零索引的):

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(islice(iterable, n, None), default)

或者,您可以使用first = nth(iteration, 0) tenth = nth(iteration, 8) # since we've already taken one hundredth = nth(iteration, 89) # since we've already taken ten # etc 并使用tee每次使用不同的迭代器。这样您就不必担心单个迭代器被消耗的事实。另一方面,如果你的迭代器很长,你可能会开始吞咽内存。

答案 2 :(得分:1)

除了如上所述查看nth之外,我还会考虑简化您的生成器:

from itertools import count

def concat():
    for i in count(1):
        for j in str(i):
            yield int(j)