首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何分割生成器对象或迭代器?

如何分割生成器对象或迭代器?
EN

Stack Overflow用户
提问于 2016-01-11 22:28:40
回答 4查看 27.3K关注 0票数 30

我想循环一个迭代器的“片段”。我不确定这是否可能,因为我知道不可能分割迭代器。我想做的是:

代码语言:javascript
复制
def f():
    for i in range(100):
        yield(i)
x = f()

for i in x[95:]:
    print(i)

当然,这在以下几个方面都失败了:

代码语言:javascript
复制
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-37-15f166d16ed2> in <module>()
  4 x = f()
  5 
----> 6 for i in x[95:]:
  7     print(i)

TypeError: 'generator' object is not subscriptable

有没有一种节奏式的方法来循环通过一个发电机的“部分”?

基本上,我所关心的生成器读取一个非常大的文件,并逐行对其执行一些操作。我想测试文件的切片,以确保事情按预期执行,但让它运行整个文件是非常耗时的。

编辑:

如前所述,我需要把这个写在一个文件上。我希望有一种方法可以在生成器中显式地指定这一点,例如:

代码语言:javascript
复制
import skbio

f = 'seqs.fna'
seqs = skbio.io.read(f, format='fasta')

seqs是一个生成器对象。

代码语言:javascript
复制
for seq in itertools.islice(seqs, 30516420, 30516432):
    #do a bunch of stuff here
    pass

上面的代码完成了我所需要的,但是仍然非常慢,因为生成器仍然遍历所有的行。我希望只在指定的切片上循环

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-01-11 23:07:35

通常是itertools.islice,但是您应该注意到,islice实际上没有跳过值,也不能跳过值。它只是在启动start -ing值之前抓取并丢弃yield值。因此,如果可能的话,最好避免使用islice,因为需要跳过许多值和/或被跳过的值获取/计算成本很高。如果您能够找到一种方法来不首先生成这些值,那么就这样做。在您(显然是人为的)示例中,您只需调整range对象的开始索引。

在试图在文件对象上运行的特定情况下,拉出大量行(特别是从慢速介质中读取)可能并不理想。假设您不需要特定的行,您可以使用一个技巧来避免实际读取文件的巨大块,同时仍然测试文件的一些距离,那就是seek到一个猜测的偏移量,读出到行的末尾(放弃您可能在中间查找的部分行),然后从那个点开始删除您想要的行数。例如:

代码语言:javascript
复制
import itertools

with open('myhugefile') as f:
    # Assuming roughly 80 characters per line, this seeks to somewhere roughly
    # around the 100,000th line without reading in the data preceding it
    f.seek(80 * 100000)
    next(f)  # Throw away the partial line you probably landed in the middle of
    for line in itertools.islice(f, 100):  # Process 100 lines
        # Do stuff with each line

对于特定的文件情况,您可能还需要查看mmap,它可以以类似的方式使用(如果您处理的是数据块而不是文本行,则非常有用,可能会随意跳来跳去)。

更新:根据您更新的问题,您需要查看您的API文档和/或数据格式,以确定如何正确地跳过。看起来像, but that's still going to read if not process most of the file。如果数据是以相同的序列长度写出的,我会查看Alignment上的文档;对齐的数据可以通过e.g s that skip the rest of the data for you加载而不需要处理前面的数据。

票数 31
EN

Stack Overflow用户

发布于 2016-01-11 22:46:09

孤岛是节奏曲的方式

代码语言:javascript
复制
from itertools import islice    

g = (i for i in range(100))

for num in islice(g, 95, None):
    print num
票数 6
EN

Stack Overflow用户

发布于 2016-01-11 22:59:58

不能使用普通的slice operations对生成器对象或迭代器进行切片。相反,您需要使用itertools.islice作为@jonrsharpe在他的comment中已经提到。

代码语言:javascript
复制
import itertools    

for i in itertools.islice(x, 95)
    print(i)

还请注意,islice返回迭代器并使用迭代器或生成器上的数据。因此,如果需要返回并执行某些操作或使用鲜为人知的itertools.tee来创建生成器的副本,则需要将数据转换为列表或创建新的生成器对象。

代码语言:javascript
复制
from itertools import tee


first, second = tee(f())
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34732311

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档