У меня есть два текстовых файла. Один содержит очень длинный список строк (100 ГБ), другой — около 30 строк. Мне нужно найти, какие строки из второго файла также есть в первом файле, и записать их в другой, третий текстовый файл. Искать каждую строку вручную — это утомительно, поэтому я хотел написать скрипт, который делал бы это автоматически. Для этого я выбираю Python, потому что это единственный язык, который я знаю хоть немного.
По сути, я попытался скопировать этот ответ, так как у меня слишком мало опыта, чтобы писать собственный код: Сравните 2 файла в Python и извлеките различия в виде строк
smallfile = 'smalllist.txt'
bigfile = 'biglist.txt'
def file_2_list(file):
with open(file) as file:
lines = file.readlines()
lines = [line.rstrip() for line in lines]
return lines
def diff_lists(lst1, lst2):
differences = []
both = []
for element in lst1:
if element not in lst2:
differences.append(element)
else:
both.append(element)
return(differences, both)
listbig = file_2_list(bigfile)
listsmall = file_2_list(smallfile)
diff, both = diff_lists(listbig, listsmall)
print(both)
Я хотел, чтобы он напечатал мне строки, которые есть в обоих списках. Однако это дало мне «ошибку памяти». Но я уже использую 64-битную версию Python, поэтому ограничение памяти не должно быть проблемой? (у меня 16 ГБ ОЗУ)
Так как же избежать этой «ошибки памяти»? Или, может быть, есть лучший способ выполнить эту задачу?
Вы действительно хотите распечатать их в виде списка? Это кажется непривычным и неудобным для дальнейшего использования. Как часто строки встречаются в большом файле? Вас волнует их порядок? Вас волнует, как часто они происходят?
Метод file.readlines
считывает файл в память целиком, чего следует избегать, если файл настолько велик.
Вместо этого вы можете прочитать строки меньшего файла в набор, а затем перебирать строки большего файла, чтобы найти общие строки, проверяя, есть ли строка в наборе:
def common_lines(small_file, big_file):
small_lines = set(small_file)
return [line for line in big_file if line in small_lines]
with open(smallfile) as file1, open(bigfile) as file2:
both = common_lines(file1, file2)
Забавная версия, которая может быть быстрее и экономить много памяти, если строки встречаются часто: d = {line: line for line in small_file}
и затем list(filter(None, map(d.get, large_file)))
.
Как вы думаете, загрузка более 100 ГБ при наличии всего лишь 16 ГБ ОЗУ не должна быть проблемой?