#python #python-3.x
Вопрос:
У меня есть большой .txt
файл, который я хочу читать по одной строке за раз (вместо того, чтобы читать все это в память, чтобы избежать проблем с нехваткой памяти), а затем извлекать все уникальные символы, присутствующие в файле. У меня есть приведенный ниже код, который хорошо работает для небольших файлов, но когда я запускаю его в большом файле (это те файлы, которые мне обычно нужны для выполнения упражнения), он выполняется очень медленно, например, около 1 часа для файла объемом 10 ГБ. Может кто-нибудь, пожалуйста, подсказать, как я могу улучшить производительность, например, путем перестановки выполняемых операций, избегая повторяющихся запусков или используя более быстрые функции.
Спасибо
def flatten(t):
'''Flatten list of lits'''
return [item for sublist in t for item in sublist]
input_file = r'C:large_text_file.txt'
output_file = r'C:char_set.txt'
#Parameters
case_sensitive = False
remove_crlf = True
#Extract all unique characters from file
charset = []
with open(input_file, 'r') as infile:
for line in infile:
if remove_crlf:
charset.append(list(line.rstrip())) #remove CRLF
else:
charset.append(list(line))
charset = flatten(charset) #flatten the list of lists
if not(case_sensitive):
charset = (map(lambda x: x.upper(), charset)) #convert to upper case
charset = list(dict.fromkeys(charset)) #remove duplicates
charset.sort(key=None, reverse=False) #sort character set in ascending order
infile.close() #close the input file
#Output the charater set
with open(output_file, 'w') as f:
for char in charset:
f.write(char)
Ответ №1:
Вы можете очень упростить это, чтобы сделать его линейным:
charset = set() # use a real set!
with open(input_file, 'r') as infile:
for line in infile:
if remove_crlf:
line = line.strip()
if not case_sensitive:
line = line.upper()
charset.update(line)
with open(output_file, 'w') as f:
for char in sorted(charset):
f.write(char)
Что сделало его квадратичным, были ли все эти строки:
charset = flatten(charset) #flatten the list of lists
charset = map(lambda x: x.upper(), charset)
charset = list(dict.fromkeys(charset))
где вы продолжаете выполнять операции с постоянно растущим списком, а не только с текущей строкой.
Некоторая документация:
Комментарии:
1. Спасибо! Позвольте мне попробовать это сейчас. Что такое
difference_update()
?2. Добавлены некоторые ссылки на документацию. Конечно, это должно было быть
update
. Исправлено.3. Это работает отлично, выполнил задание за 3 минуты! Спасибо! Только одно обновление —
charset.update(line.strip())
должно быть обновленоcharset.update(line)
, чтобы CRLF удалялся только тогда, когдаremove_crlf
для параметра установлено значениеTrue
.4. Ах, конечно. Вставил условие позже и не удалил начальную полосу.