2015-06-28 2 views
2

Задача состоит в том, чтобы объединить сортировку двух больших файлов (не помещается в память). После этого мало-мальски исследования, кажется, что это довольно легко сделать это с помощью heapq.mergeобъединить несколько отсортированных больших файлов - python

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:

яблочного

амазонка

Google

Data2.txt:

привет

сегодня

мир

Output: 

apple 
amazon 
google 
hello 
today 
world 

Мой ответ не использовать 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) 

Эта проблема также требует, чтобы оптимизировать как память и загрузку процессора. Есть ли предложения?

+0

'heapq.merge' работает только с отсортированными входными данными. Ваши файлы данных уже отсортированы? –

+0

@ SamuelO'Malley да! – wumingshi

+0

Это вопрос домашней работы? Если это так, я настоятельно рекомендую попытаться реализовать это самостоятельно без 'heapq.merge', потому что это не очень сложно и упростит пропустить пустые строки. –

ответ

2

Если вы хотите использовать 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)) 

Кроме того, этот вопрос звучит очень похоже на проблему домашнего задания (извинения, если это не так), и я бы настоятельно рекомендуем реализовать логику объединения себя, потому что это забавная проблема.

+1

Большое спасибо! Да, интересно реализовать логику слияния. Я делаю это. :-) – wumingshi

Смежные вопросы