如何使用不同的步骤迭代两个文件而不使用python将它们全部加载到内存中?

时间:2017-07-20 18:44:16

标签: python algorithm

我们说我有两个文件A和B

在A中我有100行,在B中我有10行,我需要在A中每10行和B中每1行进行一次操作。

例如在A中,我有以下几行 A1 a2 ... A10 A11 .. A20 ... A100

B中的

我有以下几行: B1 B2 ... B10

我想对数据a1,a2..a10和b1进行操作,我想再次对数据a11,a12 ... a20和b2进行操作。

所以问题是A和B都非常庞大,我无法将它们全部加载到内存中,所以我需要逐行迭代它们,但速度不同,因为A中的10行映射到B中的1行。没有预处理A,使其与B具有相同的行大小?

(我使用的是python 2.7)

3 个答案:

答案 0 :(得分:1)

标准file.readline方法将为您提供单行读取。打开文件对象不会一次将它们加载到内存中;文件被缓冲,文件位置在调用后续readline时提前。通过这种方式,你可以完成你想要的东西:

def process(a_data, b_data):
    pass  # Your code here

a_data = [None] * 10
with open('pathToFileB', 'r') as fileB:
    with open('pathToFileA', 'r') as fileA:
        for b_data in fileB:
            for i in len(a_data):
                a_data[i] = a.readline()
            process(a_data, b_data)

当然,这假设文件A确保文件B中的每一行有10行;当它到达文件A的末尾时,如果文件B中仍有行,a_data将填充None个值。

答案 1 :(得分:1)

您可以编写一些通用代码,可以打印文件a.txtb.txt中的行,具体取决于它们有多少行。

您可以如下动态推导它,甚至可以在下面的代码中对间隔(factor=10)进行硬编码。

NOTE:对于我的示例执行,a.txt有a1..a33(33行),b.txt有b1..b3(3行)

import math

## capture all data from files into a list    
alines = [line.rstrip('\n') for line in open('a.txt')]
blines = [line.rstrip('\n') for line in open('b.txt')]

## you can have your own custom factor too
## e.g. 10 as you explain in question
factor = math.ceil(len(alines) / len(blines))
print("Your factor is: " + str(factor))
print("\n")

acount = 0
bcount = 0

## iterate thru all elements of a and b file
for line in range(len(alines) + len(blines)):
    ## print b only when its turn
    if (bcount < len(blines) and (line % (factor+1)) == 0):
        print(blines[bcount])
        bcount = bcount + 1
    else:
        ## print a when its turn
        if (acount < len(alines)):
            print(alines[acount])
            acount = acount + 1

示例运行

b1
a1
a2
a3
a4
a5
a6
a7
a8
a9
a10
a11
b2
a12
a13
a14
a15
a16
a17
a18
a19
a20
a21
a22
b3
a23
a24
a25
a26
a27
a28
a29
a30
a31
a32
a33

答案 2 :(得分:1)

有一个常见的习惯用法来迭代&#34; chunk&#34;使用itertools.izip和一个解包的单个迭代器引用列表:

from itertools import izip

for values in izip(*[iter]*n): # values will hold n values at a time

出于您的目的,您可以添加对较小文件的引用以及对较大文件的多个引用(文件是迭代器):

with open("A") as file_a, open("B") as file_b:
    for values in izip(file_b, *[file_a]*10): # values will have one B value and 10 A values
        # do stuff here with the values

如果文件可能不完全对齐,您可以使用itertools.izip_longest代替常规izip。如果输入完全匹配,它将允许您提供默认值。在Python 3中,常规内置zip与{2}中的itertools.izip类似,因此您无需导入任何内容。