3

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

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

我正在尝试解决 Project Euler 的问题 40。我生成了一串连接整数

iteration = (i for i in ''.join(map(str, (i for i in xrange(1,10**6)))))

现在我想获取索引为 1、10、100、1000、10000、100000、1000000 的元素,从 1 开始计数。我不能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 等组成的序列。

4

3 回答 3

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]

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

于 2012-11-25T16:41:05.910 回答
1

这来自itertools 文档的“食谱”部分。它返回 的n第一个元素iterable,并在运行时使用它:

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

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

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和使用不同的迭代器。nth这样你就不必担心你的单个迭代器被消耗掉了。另一方面,如果您的迭代器很长,您可能会开始吞噬内存。

于 2012-11-25T16:24:29.910 回答
1

除了nth如上所述 - 我会考虑简化您的生成器:

from itertools import count

def concat():
    for i in count(1):
        for j in str(i):
            yield int(j)
于 2012-11-25T16:37:51.777 回答