сравнение двух файлов и запись отсутствующих значений в файл - PullRequest
3 голосов
/ 30 ноября 2011

У меня проблема при попытке сравнить два больших файла. То, что я пытаюсь сделать, это взять строку из одного файла, найти все строки другого файла на предмет соответствия, и, если такового нет, записать эту строку в другой файл. Мне удалось воссоздать проблему с помощью простого примера ниже:

file1.txt (содержимое )

apple
banana
pear
peach
lime

file_old.txt (содержимое)

lime
apple
pear
peach

Так как я ищу строки в file1, которых нет в file_old, я ожидаю, что 'banana' будет единственным значением, которое будет показано в выходном файле. Но в выходном файле "* fill_diff *" я показываю:

apple
banana
banana

Что не так с моим кодом, чтобы попытаться произвести различия в файле?

def main():

    file_old = open(r'C:\Users\test\Desktop\file_old.txt', 'r+')
    file_new = open(r'C:\Users\test\Desktop\file1.txt', 'r+')
    file_diff = open(r'C:\Users\test\Desktop\file_diff.txt', 'w')

    for each_line in file_new: 
        for every_line in file_old:
            if each_line == every_line:
                break
            file_diff.write(each_line)

    file_old.close()
    file_new.close()
    file_diff.close()

main()

Спасибо!

Ответы [ 6 ]

4 голосов
/ 30 ноября 2011

srgerg ответ будет работать.

Однако многократное чтение файлов будет иметь очень большую сложность во время выполнения.Поэтому, если файлы (хотя и большие) достаточно малы, чтобы поместиться в память, вы можете рассмотреть возможность помещения всех строк в file_old в структуру данных для сравнения:

old_lines = set((line.strip() for line in open(r'C:\Users\test\Desktop\file_old.txt', 'r+')))
file_new = open(r'C:\Users\test\Desktop\file1.txt', 'r+')
file_diff = open(r'C:\Users\test\Desktop\file_diff.txt', 'w')

for line in file_new:
    if line.strip() not in old_lines:
        file_diff.write(line)
file_new.close()
file_diff.close()

Надеюсь, это поможет

2 голосов
/ 30 ноября 2011

Вы можете сделать это в O (n + n * log (n)), сначала отсортировав оба файла, а затем итерируя оба одновременно.

# sort file1 and file2 on disk or in memory
while len(file1) > 0 and len(file2) > 0:
    while file1[0] < file2[0]:
        diff.append(file1[0])
        file1 = file1[1:]
    while file1[0] > file2[0]:
        diff.append(file2[0])
        file2 = file2[1:]
    while file1[0] == file2[0]:
        file1 = file1[1:]
        file2 = file2[1:]
diff = diff + file1 + file2 # add the rest to the diff
1 голос
/ 30 ноября 2011

Я подозреваю, что вы хотите пропустить строки в любом порядке ?

Это быстрая и грязная реализация, основанная на set():

def readfile(name):
    afile = open(name, 'r+')
    lines = set([l.strip() for l in afile])
    afile.close()
    return lines

def main():
    oldset = readfile(r'file_old.txt')
    newset = readfile(r'file1.txt')

    file_diff = open(r'file_diff.txt', 'w')

    for diff in (newset - oldset):
        file_diff.write(diff)

    file_diff.close()

main()

Это может не очень хорошо масштабироваться для очень больших входных файлов.

1 голос
/ 30 ноября 2011

FWIW, difflib модуль был разработан для этого вида использования.

Если вам нужно сделать это вручную, наборы Python могут сделать это проще:

file_diff = open(r'C:\Users\test\Desktop\file_diff.txt', 'w')
oldlines = set(open(r'C:\Users\test\Desktop\file_old.txt', 'r'))
for line in open(r'C:\Users\test\Desktop\file1.txt', 'r'):
    if line not in oldlines:
        file_diff.write(line)
1 голос
/ 30 ноября 2011

Вам нужно вернуться к началу file_old в начале каждой итерации вашего цикла.Примерно так:

for each_line in file_new:
    file_old.seek(0)
    for every_line in file_old:
        ...

Кроме того, логика вашего внутреннего цикла кажется неправильной.Я думаю, что вы хотите что-то вроде

for each_line in file_new:
    file_old.seek(0)
    found = False
    for every_line in file_old:
        if each_line == every_line:
            found = True
            break

    if not found:
        file_diff.write(each_line)
0 голосов
/ 30 ноября 2011

Если вы не можете предположить, что файлы отсортированы, то я бы сделал что-то вроде этого

def diffUnsorted(fn1, fn2) :
    return set([l.strip() for l in open(fn1) if l.strip() != ""]) - \
           set([l.strip() for l in open(fn2) if l.strip() != ""])

Если вы собираетесь работать с большими файлами, я бы пошел срешение, которое сортирует файлы первым, что дает вам O (n) время и O (1) пространство (не считая сортировку ..).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...