在Python中获取生成器的第n项

时间:2010-02-20 02:11:36

标签: python generator

是否有更复杂的语法编写方式?

gen = (i for i in xrange(10))
index = 5
for i, v in enumerate(gen):
    if i is index:
        return v

生成器应该有一个gen[index]表达式,它充当列表,但在功能上与上面的代码完全相同似乎很自然。

9 个答案:

答案 0 :(得分:51)

一种方法是使用itertools.islice

>>> next(itertools.islice(xrange(10), 5, 5 + 1))
5

答案 1 :(得分:15)

您可以使用count作为示例生成器执行此操作:

from itertools import islice, count
next(islice(count(), n, n+1))

答案 2 :(得分:3)

我认为最好的方法是:

next(x for i,x in enumerate(it) if i==n)

(其中it是您的迭代器,n是索引)

既不需要添加导入(例如使用itertools的解决方案),也不需要一次将迭代器的所有元素加载到内存中(例如使用list的解决方案)。< / p>

注1:如果迭代器的项目少于n个,则此版本将引发StopIteration错误。如果您想获得None,可以使用:

next((x for i,x in enumerate(it) if i==n), None)

注2:next的调用内没有括号。这不是列表推导,而是生成器推导,它不会消耗原始迭代器的第n个元素。

答案 3 :(得分:1)

我反对对待列表等生成器的诱惑。简单但天真的方法是简单的单行:

gen = (i for i in range(10))
list(gen)[3]

但请记住,生成器并不像列表。他们不会在任何地方存储他们的中间结果,因此您无法倒退。我将通过python repl中的一个简单示例演示此问题:

>>> gen = (i for i in range(10))
>>> list(gen)[3]
3
>>> list(gen)[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

一旦开始通过生成器获取序列中的第n个值,生成器现在处于不同的状态,并且尝试再次获取第n个值将返回不同的结果,这可能会导致你的代码中的错误。

让我们根据问题中的代码来看一个另一个例子。

最初需要以下两次打印4

gen = (i for i in range(10))
index = 4
for i, v in enumerate(gen):
    if i == index:
        answer = v
        break
print(answer)
for i, v in enumerate(gen):
    if i == index:
        answer = v
        break
print(answer)

但是将其输入到repl中即可获得:

>>> gen = (i for i in range(10))
>>> index = 4
>>> for i, v in enumerate(gen):
...     if i == index:
...             answer = v
...             break
... 
>>> print(answer)
4
>>> for i, v in enumerate(gen):
...     if i == index:
...             answer = v
...             break
... 
>>> print(answer)
9

祝你好运追踪那个错误。

编辑:

正如所指出的,如果生成器无限长,您甚至无法将其转换为列表。表达式list(gen)永远不会完成。

有一种方法可以将一个懒惰的评估缓存包装器放在一个无限的生成器周围,使它看起来像一个无限长的列表,你可以随意索引,但这值得自己的问答,并会产生重大的性能影响

答案 4 :(得分:1)

最适合使用的是: 示例:

a = gen values ('a','c','d','e')

所以答案将是:

a = list(a) -> this will convert the generator to a list (it will store in memory)

然后,当您要查找特定索引时,您将:

a[INDEX] -> and you will able to get the value its holds 

如果您只想知道计数或执行不需要存储在内存中的最佳操作,将是: a = sum(1 in i in a)->这将计算您拥有的对象数量

希望我使它更简单。

答案 5 :(得分:0)

我想到的第一件事就是:

$ docker exec -it postgres-container bash

# su postgres

$ psql

答案 6 :(得分:0)

如果n在创作时是已知的,则可以使用解构。例如获得第三项:

>>> [_, _, third, *rest] = range(10)
>>> third
2
>>> rest
[3, 4, 5, 6, 7, 8, 9]

答案 7 :(得分:-2)

也许您应该详细说明实际用例。

>>> gen = xrange(10)
>>> ind=5 
>>> gen[ind]
5

答案 8 :(得分:-2)

您可以将生成器转换为列表并正常使用索引:

>>> [i for i in range(10)][index]
5
相关问题