简体   繁体   English

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

[英]Get multiple individual values from generator in Python

How do i take multiple arbitrary values from different index positions in an iterator? 如何从迭代器的不同索引位置获取多个任意值?

How to get the n next values of a generator in a list (python) and Get the nth item of a generator in Python describe the use of itertools.islice for taking arbitrary element or continuous subset from an iterator. 如何在列表(python)中 获取 生成器的n个下一个值以及如何 在Python获取生成器的n个项,描述了itertools.islice用于从迭代器获取任意元素或连续子集的用法。 But what if i want multiple arbitrary elements from different positions in the iterator, where you can't just use islice 's step argument? 但是,如果我想要迭代器中不同位置的多个任意元素,而不能仅仅使用islice的step参数呢?

I'm trying to solve Project Euler's problem 40 . 我正在尝试解决Euler项目的问题40 I generated a string of concatenated integers with 我生成了一个由串联的整数组成的字符串

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

An now i want to get elements with indexes 1, 10, 100, 1000, 10000, 100000, 1000000 counting from 1. I couldn't use islice here, because every call to next shifts current value to yield to the right. 现在,我想从索引1开始获得索引为islice在这里我不能使用islice ,因为每次调用next都会使当前值右移。 For example 例如

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

produces '26' instead of '24'. 产生“ 26”而不是“ 24”。

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

Thanks for all the suggestions. 感谢所有的建议。 My current code looks like: 我当前的代码如下:

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)

The ugly argument for nth is to generate a sequence of 0, 8, 89, 899, 8999 etc. nth的丑陋参数是生成0、8、89、899、8999等的序列。

(Note that there are much faster ways to solve Euler #40.) (请注意,有更快的方法可以解决Euler#40。)

I would work a little differently. 我的工作方式会有所不同。 Instead of using nth : 而不是使用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]

This way I don't have to do any subtractions to make sure I have the right indices. 这样,我不必进行任何减法操作即可确保索引正确。

This is from the "recipes" section of the itertools documentation . 这是来自itertools文档的“食谱”部分 It returns the n th element of iterable , consuming it as it goes: 它返回iterablen个元素,并随其使用:

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

You can get the 1st, 10th, 100th etc elements by calling it sequentially (noting that the iterator gets consumed, and is zero-indexed): 您可以通过依次调用它来获得1st,10th,100th等元素(请注意,迭代器已消耗,并且索引为零):

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

Alternatively, you could use tee and use nth with a different iterator each time. 另外,您可以每次使用tee并使用nth和不同的迭代器。 This way you don't have to worry about the fact that your single iterator is getting consumed. 这样,您不必担心单个迭代器被消耗的事实。 On the other hand you might start swallowing memory if your iterators are very long. 另一方面,如果迭代器很长,则可能开始吞下内存。

As well as looking at nth as mentioned - I would look at simplifying your generator: 就像提到的那样查看nth我将着眼于简化生成器:

from itertools import count

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM