重置python迭代计数_可以在Python中重置迭代器吗?

可以在Python中重置迭代器吗?

我可以在Python中重置迭代器/生成器吗? 我正在使用DictReader并希望将其重置(从csv模块)到文件的开头。

13个解决方案

68 votes

我看到许多回答暗示了itertools.tee,但是它忽略了文档中的一个重要警告:

这个itertool可能需要很多   辅助存储(取决于如何   需要很多临时数据  存储)。 一般来说,如果一个迭代器   之前使用大部分或全部数据   另一个迭代器启动,它更快   使用list()而不是csv。

基本上,csv是针对一个迭代器的两个(或更多)克隆,而#34;不同步的情况而设计的。 相互之间不要这么做 - 相反,他们会在同一个地方说#34;附近" (一些项目背后或相互提前)。 不适合OP从一开始就重做的问题"重做。

另一方面,csv非常适合,只要序列表可以很好地适应内存。 一个新的"迭代器从一开始" (非常轻量级,低开销)可随时用.seek(0)制作,部分或全部使用而不影响新的或现有的; 其他访问模式也很容易获得。

正如几个答案正确地说,在csv的具体情况下,您也可以.seek(0)底层文件对象(一个相当特殊的情况)。 我不确定这些文件是否有记录和保证,尽管它目前有效; 它可能值得考虑仅用于真正巨大的csv文件,其中list我推荐作为一般方法将具有太大的内存占用。

Alex Martelli answered 2019-07-24T07:35:10Z

29 votes

如果您有一个名为' blah.csv'的csv文件 看起来像

a,b,c,d

1,2,3,4

2,3,4,5

3,4,5,6

你知道你可以打开文件进行阅读,并创建一个DictReader

blah = open('blah.csv', 'r')

reader= csv.DictReader(blah)

然后,您将能够获得reader.next()的下一行,该行应该输出

{'a':1,'b':2,'c':3,'d':4}

再次使用它会产生

{'a':2,'b':3,'c':4,'d':5}

但是,此时如果您使用blah.seek(0),下次拨打reader.next()时,您将获得

{'a':1,'b':2,'c':3,'d':4}

再次。

这似乎是您正在寻找的功能。 我确定有一些与这种方法相关的技巧,但我并不知道。 @Brian建议简单地创建另一个DictReader。 如果您的第一个读者在读取文件的一半时,这将无法工作,因为您的新读者将从文件中的任何位置获得意外的键和值。

Wilduck answered 2019-07-24T07:36:19Z

21 votes

不可以.Python的迭代器协议非常简单,只提供一种方法(itertools.tee或__next__()),并且通常没有方法来重置迭代器。

常见的模式是再次使用相同的过程创建一个新的迭代器。

如果你想"保存" 一个迭代器,以便你可以回到它的开头,你也可以通过使用itertools.tee来分叉迭代器

u0b34a0f6ae answered 2019-07-24T07:37:00Z

10 votes

使用上面的Alex Martelli和Wilduck所倡导的.seek(0)是一个错误,即下一次调用.next()将以{key1:key1的形式为您提供标题行的字典, key2:key2,...}。 解决方法是跟随file.seek(0)调用reader.next()来删除标题行。

所以你的代码看起来像这样:

f_in = open('myfile.csv','r')

reader = csv.DictReader(f_in)

for record in reader:

if some_condition:

# reset reader to first row of data on 2nd line of file

f_in.seek(0)

reader.next()

continue

do_something(record)

Steven Rumbalski answered 2019-07-24T07:37:34Z

10 votes

是的,如果您使用numpy.nditer来构建迭代器。

>>> lst = [1,2,3,4,5]

>>> itr = numpy.nditer([lst])

>>> itr.next()

1

>>> itr.next()

2

>>> itr.finished

False

>>> itr.reset()

>>> itr.next()

1

Developer answered 2019-07-24T07:38:02Z

3 votes

这可能与原始问题正交,但可以将迭代器包装在返回迭代器的函数中。

def get_iter():

return iterator

要重置迭代器,只需再次调用该函数。如果所述函数不带参数时的函数,这当然是微不足道的。

在函数需要一些参数的情况下,使用functools.partial创建一个可以传递而不是原始迭代器的闭包。

def get_iter(arg1, arg2):

return iterator

from functools import partial

iter_clos = partial(get_iter, a1, a2)

这似乎避免了tee(n份)或list(1份)需要执行的缓存

Anish answered 2019-07-24T07:38:50Z

2 votes

虽然没有迭代器重置,但是#34; itertools" 来自python 2.6(及更高版本)的模块有一些可以帮助的实用程序。其中之一就是" tee" 它可以生成迭代器的多个副本,并缓存前面运行的结果,以便在副本上使用这些结果。 我会把你的目的:

>>> def printiter(n):

... for i in xrange(n):

... print "iterating value %d" % i

... yield i

>>> from itertools import tee

>>> a, b = tee(printiter(5), 2)

>>> list(a)

iterating value 0

iterating value 1

iterating value 2

iterating value 3

iterating value 4

[0, 1, 2, 3, 4]

>>> list(b)

[0, 1, 2, 3, 4]

jsbueno answered 2019-07-24T07:39:20Z

1 votes

对于小文件,您可以考虑使用DictReader - 提供重置可迭代的第三方工具。

演示

import csv

import more_itertools as mit

filename = "data/iris.csv"

with open(filename, "r") as f:

reader = csv.DictReader(f)

iterable = mit.seekable(reader) # 1

print(next(iterable)) # 2

print(next(iterable))

print(next(iterable))

print("\nReset iterable\n--------------")

iterable.seek(0) # 3

print(next(iterable))

print(next(iterable))

print(next(iterable))

产量

{'Sepal width': '3.5', 'Petal width': '0.2', 'Petal length': '1.4', 'Sepal length': '5.1', 'Species': 'Iris-setosa'}

{'Sepal width': '3', 'Petal width': '0.2', 'Petal length': '1.4', 'Sepal length': '4.9', 'Species': 'Iris-setosa'}

{'Sepal width': '3.2', 'Petal width': '0.2', 'Petal length': '1.3', 'Sepal length': '4.7', 'Species': 'Iris-setosa'}

Reset iterable

--------------

{'Sepal width': '3.5', 'Petal width': '0.2', 'Petal length': '1.4', 'Sepal length': '5.1', 'Species': 'Iris-setosa'}

{'Sepal width': '3', 'Petal width': '0.2', 'Petal length': '1.4', 'Sepal length': '4.9', 'Species': 'Iris-setosa'}

{'Sepal width': '3.2', 'Petal width': '0.2', 'Petal length': '1.3', 'Sepal length': '4.7', 'Species': 'Iris-setosa'}

这里DictReader包含在seekable对象(1)和高级(2)中。 seek()方法用于将迭代器重置/倒回到第0位置(3)。

注意:内存消耗随着迭代而增长,因此请谨慎地将此工具应用于大型文件,如文档中所示。

pylang answered 2019-07-24T07:40:07Z

1 votes

问题

我之前遇到过同样的问题。 在分析了我的代码之后,我意识到尝试重置循环内部的迭代器会稍微增加时间复杂度,这也会使代码变得有点丑陋。

打开文件并将行保存到内存中的变量。

# initialize list of rows

rows = []

# open the file and temporarily name it as 'my_file'

with open('myfile.csv', 'rb') as my_file:

# set up the reader using the opened file

myfilereader = csv.DictReader(my_file)

# loop through each row of the reader

for row in myfilereader:

# add the row to the list of rows

rows.append(row)

现在,您可以在范围内的任何位置循环遍历行,而无需处理迭代器。

Anthony Holloman answered 2019-07-24T07:40:53Z

0 votes

仅当基础类型提供了这样做的机制时(例如fp.seek(0))。

Ignacio Vazquez-Abrams answered 2019-07-24T07:41:21Z

0 votes

对于DictReader:

f = open(filename, "rb")

d = csv.DictReader(f, delimiter=",")

f.seek(0)

d.__init__(f, delimiter=",")

对于DictWriter:

f = open(filename, "rb+")

d = csv.DictWriter(f, fieldnames=fields, delimiter=",")

f.seek(0)

f.truncate(0)

d.__init__(f, fieldnames=fields, delimiter=",")

d.writeheader()

f.flush()

mAsT3RpEE answered 2019-07-24T07:41:54Z

0 votes

list(generator())返回生成器的所有剩余值,如果没有循环,则会有效地重置它。

Theoremiser answered 2019-07-24T07:42:22Z

0 votes

可能的选择是使用itertools.cycle(),它允许无限期迭代而不需要像.seek(0)这样的技巧

iterDic = itertools.cycle(csv.DictReader(open('file.csv')))

Greg H answered 2019-07-24T07:42:50Z

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值