在一个可迭代的对象上迭代多次

时间:2018-12-07 15:37:34

标签: python

我试图对一个可迭代对象进行多次迭代。但是,问题在于,一旦迭代器被消耗,它就无法再产生收益。这意味着,在我第一次迭代后,我不再可以使用可迭代对象。
就我而言,我有一个10000行的excel文件,我正在创建一个textfilereader,以避免将我的所有数据导入内存中。我正在修复许多迭代,这些迭代将用于在excel文件的行上执行相同的操作。由于iterable的淡入淡出的性质,我无法在第二次迭代后使用这些操作。因此,我尝试创建一个全局iteraton循环,每次都在其中定义可迭代项:是否有更好的方法来解决此问题

在我的情况下,使用iterable的主要原因是避免将数据加载到内存中。

  

引起问题的代码

### read file through an iterable
df_test = pd.read_csv('filet_to_read.csv',sep=';',quotechar='"', escapechar='\\', iterator=True, chunksize=15, encoding='utf-8',converters={'Ident':str})
### iterations
iterations=5
for iter in range(iterations):
    for chunk in df_test:
          ##Do_operations
    print('end of itertaion :',iter)

### After first iteration, no more operations are possible because iterable is consumed
  

我的解决方案

iterations=5
    for i in range(iterations):
        df_test = pd.read_csv('filet_to_read.csv',sep=';',quotechar='"', escapechar='\\', iterator=True, chunksize=15, encoding='utf-8',converters={'Ident':str})
        for chunk in df_test:
              ##Do_operations
        print('end of itertaion :',iter)

2 个答案:

答案 0 :(得分:4)

您可以从文档中使用tee

  

从单个可迭代对象中返回n个独立的迭代器。

示例

from itertools import tee


it = range(5)

for i in tee(it, 5):
    print(list(i))

输出

[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]

答案 1 :(得分:0)

我遇到了一个与您非常相似的问题。我需要多次遍历数据库表而不将其保留在内存中。上面的解决方案不能解决我的问题,因为我的代码需要多次传递迭代器并传递给不同级别的许多函数。我想出了一个解决方案,我认为它比tee更优雅,更通用,并想在这里分享。

此“ looper”类将使您可以多次迭代任何迭代器,只需在内部迭代器引发StopIteration后重新生成迭代器即可。外部循环程序类在重新生成之前确实引发StopIteration异常。意味着当n = None时,它将具有与列表或元组类似的迭代器行为。

class looper:
    def __init__(self, gen_iter_func,n=None):
        self.gen_iter_func = gen_iter_func
        self.n = n

    def __iter__(self):
        self.iterable = self.gen_iter_func()
        return self

    def __next__(self):
        if (self.n is not None and self.n <= 0):
            raise StopIteration
        try:
            return next(self.iterable)
        except:
            if self.n is not None:
                self.n -= 1
            raise StopIteration

使用范围的示例:

def gen_iter():
    return iter(range(5))

loop = looper(gen_iter,n=3)
for i in range(5):
    print('-------{}-------'.format(i))
    for x in loop:
        print(x)

输出:

-------0-------
0
1
2
3
4
-------1-------
0
1
2
3
4
-------2-------
0
1
2
3
4
-------3-------
-------4-------