Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 8, 2015 07:49:06

russian_bear
Зарегистрирован: 2014-09-23
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

сравнение текстовых файов

Здравствуйте друзья,

сорри за тупой вопрос, но нужна помощь новичку:
Как сравнить построчно содержимое двух текстовых файлов? Есть два текстовых файла(кол-во строк у файлов разное) со списками доменов, содержимое файлов представляет собой простой построчный список :
domain1.ru
domain2.ru
и т.д.
Нужно сравнить построчно содержимое двух текстовых файлов “file_domains1.txt” и “file_domains2.txt” на предмет совпадения доменов(совпадения строк), большинство доменов в двух файлах совпадают и задача состоит в том чтобы найти такие домены которые присутствуют только в одном из файлов(и сохранить их в “output.txt”)

большое спасибо за помощь

Отредактировано russian_bear (Янв. 8, 2015 08:04:21)

Офлайн

#2 Янв. 8, 2015 09:42:55

Alen
Зарегистрирован: 2013-08-01
Сообщения: 373
Репутация: +  49  -
Профиль   Отправить e-mail  

сравнение текстовых файов

Вообще-то для этого существует утилита diff и ей подобные, но код на python может быть, например, таким:

import sys
def diff(file_one, file_two):
    with open(file_one) as text_one, open(file_two) as text_two:
        one = set(text_one.read().split('\n'))
        two = set(text_two.read().split('\n'))
    return one ^ two
if __name__ == '__main__':
    if len(sys.argv) > 2:   
        print ('\n'.join(diff(sys.argv[1], sys.argv[2])) 
     

Вызов соответственно:
./myprogram.py file1.txt file2.txt > output.txt

Отредактировано Alen (Янв. 8, 2015 09:51:32)

Офлайн

#3 Янв. 8, 2015 10:53:32

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10015
Репутация: +  857  -
Профиль   Отправить e-mail  

сравнение текстовых файов

Alen
Вообще-то для этого существует утилита diff
Есть difflib, которая реализует такой формат.

Alen
one = set(text_one.read().split('\n'))

Можно сократить до
one = set(text_one)
переводы строк останутся.

С учётом этого, можно всё сократить
def diff(file_one, file_two):
    with open(file_one) as text_one, \
         open(file_two) as text_two:
        return set(text_one) ^ set(text_two)



Отредактировано py.user.next (Янв. 8, 2015 11:00:22)

Офлайн

#4 Янв. 8, 2015 12:00:39

russian_bear
Зарегистрирован: 2014-09-23
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

сравнение текстовых файов

друзья, всем большое спасибо !

спасибо за “наводку” на модуль difflib, с его помощью получился вот такой работающий код:
import difflib

file1 = open('domains1.txt', ‘r’)
file2 = open('domains2.txt', ‘r’)

diff = difflib.ndiff(file1.readlines(), file2.readlines())
delta = ''.join(x for x in diff if x.startswith('- '))

f = open(“out_difference.txt”,“w”)
f.write(delta)
f.close()

print delta

Офлайн

#5 Янв. 9, 2015 11:19:20

russian_bear
Зарегистрирован: 2014-09-23
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

сравнение текстовых файов

столкнулся с проблемой при работе с большими файлами. Если оба файла имеют несколько десятков строк - прога отрабатывает мгновенно, если несколько сотен - уже заметно долго, запустил на сравнение двух файлов по 3000 строк в каждом - не дождался результата, пришлось прибить процесс python.exe. А вообще мне надо сравнивать два файла у которых около 200 000 строк в каждом, получается нужно суперкомпьютер покупать ?
Друзья, подскажите, правильно-ли я понимаю что :
1)сложность вычислений при увеличении кол-ва строк возрастает квадратично т.к. при 100 строках в каждом файле мы имеем 100*100 = 10 000 операций сравнений, а при 10 000 строках в каждом файле уже 100 000 000 (сто миллионов !) операций сравнений , так ?
2)python в принципе высокоуровневый язык и не заточен под такие операции, подозреваю что прога написанная на C++ выполняла-бы подобные операции быстрее чем прога на python, так ?

спасибо

Офлайн

#6 Янв. 9, 2015 11:57:24

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10015
Репутация: +  857  -
Профиль   Отправить e-mail  

сравнение текстовых файов

russian_bear
столкнулся с проблемой при работе с большими файлами.

russian_bear
diff = difflib.ndiff(file1.readlines(), file2.readlines())

Попробовал подать туда итераторы, но ndiff() требует наличия len().
Оптимизация несущественная, но кортежи требуют меньше времени, чем списки, которые выдаёт readlines().
diff = difflib.ndiff(tuple(file1), tuple(file2))
Можно и без ndiff() обойтись при помощи множеств, как было вначале. Тем более, что ndiff() написана на питоне, оттуда и медленная скорость.

russian_bear
delta = ''.join(x for x in diff if x.startswith('- '))
Не нужно делать .join(), пиши сразу в файл вывода через .writelines().
delta = (x for x in diff if x.startswith('- '))
f.writelines(delta)

russian_bear
запустил на сравнение двух файлов по 3000 строк в каждом - не дождался результата
Вот после этих изменений проверь.


russian_bear
что прога написанная на C++ выполняла-бы подобные операции быстрее чем прога на python, так ?
У питона время уходит на интерпретацию кода скрипта, тогда как diff - это скомпилированная программа.
Посмотришь исходники, как она сравнивает. Быстрее программы не найдёшь.
http://www.gnu.org/software/diffutils/diffutils.html
http://ftp.gnu.org/gnu/diffutils/



Отредактировано py.user.next (Янв. 9, 2015 12:35:44)

Офлайн

#7 Янв. 9, 2015 12:15:10

Alen
Зарегистрирован: 2013-08-01
Сообщения: 373
Репутация: +  49  -
Профиль   Отправить e-mail  

сравнение текстовых файов

Почему вы не используйте, то что вам изначально дали.

#!/usr/bin/env python
from random import randint
def generate_file_for_compare():
    with open('1.txt', 'w') as one, 
           open('2.txt', 'w') as two:
        for _ in range(200000):
            one.write('{!s}\n'.format(randint(1, 10000)))
            two.write('{!s}\n'.format(randint(5000, 15000)))
def diff():
    with open('1.txt') as text_one,
            open('2.txt') as text_two:
    return set(text_one) ^ set(text_two)
if __name__ == '__main__':
    generate_file_for_compare()
    with open('result.txt', 'w') as result:
        for i in diff():
            result.write(i)

Время исполнения на 200 тысячах записей: 2.5 секунды, причем процентов 95% ушло на генерацию файлов.

Отредактировано Alen (Янв. 9, 2015 12:45:00)

Офлайн

#8 Янв. 9, 2015 12:47:08

russian_bear
Зарегистрирован: 2014-09-23
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

сравнение текстовых файов

Alen
from random import randint
def generate_file_for_compare():
with open('1.txt', ‘w’) as one, open('2.txt', ‘w’) as two:
for _ in range(10000):
one.write('{!s}\n'.format(randint(1, 10000)))
two.write('{!s}\n'.format(randint(5000, 15000)))
def diff():
with open('1.txt') as text_one, open('2.txt') as text_two:
return set(text_one) ^ set(text_two)
if __name__ == ‘__main__’:
generate_file_for_compare()
with open('result.txt', ‘w’) as result:
for i in diff():
result.write(str(i))

спасибо.
но в результате исполнения этого кода на выходе получаю просто какие-то цифири типа
5064
8244
11048
10354
13086
8796
2298
но нет собственно самих строк из файлов. А нужны именно сами оригинальные строки из входных файлов.

Офлайн

#9 Янв. 9, 2015 12:49:46

russian_bear
Зарегистрирован: 2014-09-23
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

сравнение текстовых файов

py.user.next

спасибо.
Но скорость осталась прежней. Результаты эксперимента:
2 файла по 1000 строк в каждом.
-оригинальный код - 24 сек.
-оптимизированный код - 24 сек.
-Liberty Basic код - 9 сек.
(Вспомнил язык который когда-то изучал, Libarty Basic называется, http://www.libertybasic.com/ , написал код для этой-же задачи, код прицепляю)

Прикреплённый файлы:
attachment liberty_basic_comparison.bas (740 байт)

Офлайн

#10 Янв. 9, 2015 12:52:44

Alen
Зарегистрирован: 2013-08-01
Сообщения: 373
Репутация: +  49  -
Профиль   Отправить e-mail  

сравнение текстовых файов

russian_bear
спасибо.
но в результате исполнения этого кода на выходе получаю просто какие-то цифири типа

Естественно у меня нет ваших файлов с данными и они генерируются прямо из программы.
Специально для вас:

#!/usr/bin/env python
def diff():
    with open('domains1.txt') as text_one, \
            open('domains2.txt') as text_two:
        return set(text_one) ^ set(text_two)
if __name__ == '__main__':
    with open('res.txt', 'w') as result:
        for i in diff():
            result.write(i)

Результат в ‘res.txt’ . Время выполнения на 200 000 записей - 0.2 секунды.

Отредактировано Alen (Янв. 9, 2015 13:08:45)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version