合并多个已排序的大文件--python
任务是合并排序两个大文件(无法放入内存)。在做了一些研究之后,使用合并多个已排序的大文件--python,python,algorithm,sorting,merge,mergesort,Python,Algorithm,Sorting,Merge,Mergesort,任务是合并排序两个大文件(无法放入内存)。在做了一些研究之后,使用heapq.merge import heapq import contextlib filenames=('data1.txt', 'data2.txt') with contextlib.ExitStack() as stack: files = [stack.enter_context(open(fn)) for fn in filenames] with open('data', 'w') as f:
heapq.merge
import heapq
import contextlib
filenames=('data1.txt', 'data2.txt')
with contextlib.ExitStack() as stack:
files = [stack.enter_context(open(fn)) for fn in filenames]
with open('data', 'w') as f:
f.writelines(heapq.merge(*files))
问题是如何处理文件中的空行。例如:
Data1.txt:
苹果
亚马逊
谷歌
Data2.txt:
你好
今天
世界
我对不使用heapq.merge的回答:
def read_non_empty_line(input):
while True:
line = input.readline()
if line == "":
return ""
if line.isspace() == False:
return line.strip()
#return line
def combine_sorted_files(file1, file2, output):
read_file1, read_file2 = True, True
with open(output,'w') as output_file:
with open(file1,'r') as input_file1:
with open(file2,'r') as input_file2:
while True:
if read_file1:
line1 = read_non_empty_line(input_file1)
if read_file2:
line2 = read_non_empty_line(input_file2)
if line1 == "" or line2 == "":
break
read_file1, read_file2 = False, False
if line1 < line2:
smaller = line1
read_file1 = True
else:
smaller = line2
read_file2 = True
output_file.write(smaller+"\n\n")
while line1 != "":
output_file.write(line1+"\n\n")
line1 = read_non_empty_line(input_file1)
while line2 != "":
output_file.write(line2+"\n\n")
line2 = read_non_empty_line(input_file2)
def读取非空行(输入):
尽管如此:
line=input.readline()
如果行==“”:
返回“”
如果line.isspace()==False:
返回行.strip()
#回程线
def合并已排序的文件(文件1、文件2、输出):
read_file1,read_file2=True,True
将open(output,'w')作为输出文件:
以open(file1,'r')作为输入\u file1:
以open(file2,'r')作为输入\u file2:
尽管如此:
如果读取文件1:
line1=读取\非\空\行(输入\文件1)
如果读取文件2:
line2=读取\非\空\行(输入\文件2)
如果第1行==“”或第2行==“”:
打破
read_file1,read_file2=False,False
如果第1行<第2行:
较小=第1行
read_file1=True
其他:
较小=第2行
read_file2=True
输出文件。写入(较小的+“\n\n”)
而第1行!="":
输出文件。写入(第1行+“\n\n”)
line1=读取\非\空\行(输入\文件1)
而第2行!="":
输出文件。写入(第2行+“\n\n”)
line2=读取\非\空\行(输入\文件2)
这个问题还要求优化内存和CPU利用率。有什么建议吗?如果要在跳过空行时使用
heapq.merge
,可以创建自己的生成器函数来处理跳过逻辑:
def iterate_non_blank_lines(file_iterator):
for line in file_iterator:
if line != "":
yield line
注意:我只是检查了空行,但您可以在这里轻松地使用正则表达式跳过仅包含空格的行
然后可以修改代码以使用此生成器:
filenames=('data1.txt', 'data2.txt')
with contextlib.ExitStack() as stack:
files = [iterate_non_blank_lines(stack.enter_context(open(fn))) for fn in filenames]
with open('data', 'w') as f:
f.writelines(heapq.merge(*files))
此外,这个问题听起来很像家庭作业问题(如果不是,则为同位语),我强烈建议您自己实现合并逻辑,因为这是一个有趣的问题。
heapq.merge
仅适用于已排序的输入数据。你的数据文件已经分类了吗?@SamuelO'Malley是的!这是家庭作业问题吗?如果是这样的话,我强烈建议您自己尝试在不使用heapq.merge
的情况下实现这一点,因为这不是很难,而且会使跳过空行变得非常容易。@SamuelO'Malley,明白了。我将在没有heaq.merge的情况下实现它,然后发布它。在那之后,你能回答这个问题吗?我对使用heaq.merge也很感兴趣。我会给heapq.merge一个答案,如果它不起作用,请告诉我。非常感谢!是的,实现合并逻辑很有趣。我正在做。:-)
filenames=('data1.txt', 'data2.txt')
with contextlib.ExitStack() as stack:
files = [iterate_non_blank_lines(stack.enter_context(open(fn))) for fn in filenames]
with open('data', 'w') as f:
f.writelines(heapq.merge(*files))