#python #python_3x #файлы #строки #обработка
Есть текстовой файл, в нём 1000 Email-ов, каждый Email с новой строки. Часть из них
повторяются. Необходимо, чтобы на выходе после обработки был файл только с уникальными
Email-ами. Как это реализовать с помощью Python 3?
Ответы
Ответ 1
Самый быстрый и простой способ убрать дубликаты из списка - преобразовать его к множеству.
Конструктор множества set() принимает любой итерируемый объект, в том числе дескриптор
файла. После чего остаётся только преобразовать множество обратно в строку и записать
в другой файл:
with open('emails.txt') as in_fh, open('deduplicated.txt', 'w') as out_fh:
out_fh.write(''.join(set(in_fh)))
Ответ 2
Чтобы напечатать уникальные e-mail, заданные в файлах, указанных в командной строке,
или из стандартного ввода:
#!/usr/bin/env python
import fileinput
print("\n".join(set(map(str.strip, fileinput.input()))))
Пример:
$ dedup emails.txt >uniq-emails.txt
или:
$ dedup < emails.txt >uniq-emails.txt
Код работает даже, если невидимый пробел присутствует/отсутствует в строках. К примеру,
последняя строчка в файле может иметь/не иметь новой строки—результат всё равно будет
правильным.
Наличие set() ведёт к тому, что результат печатается в произвольном порядке, который
может меняться от запуска к запуску. Чтобы эмулировать sort -u emails.txt, можно использовать
groupby(sorted()):
#!/usr/bin/env python
import fileinput
from itertools import groupby
for line, _ in groupby(sorted(map(str.strip, fileinput.input()))):
print(line)
Использование такое же: ввод читается из файлов или stdin, вывод печатается в stdout.
Для случая с e-mail это не нужно, но в общем случае, чтобы напечатать только уникальные
строки из больших файлов, которые в памяти не умещаются—аналогLC_ALL=C sort -u < input
в Питоне:
#!/usr/bin/env python3
import contextlib
import heapq
import sys
from itertools import groupby
from tempfile import TemporaryFile
from operator import itemgetter
def uniq(sorted_items):
return map(itemgetter(0), groupby(sorted_items))
sorted_files = []
with contextlib.ExitStack() as stack:
# sort lines in batches, write intermediate result to temporary files
nbytes = 1 << 15 # read ~nbytes at a time
for lines in iter(lambda f=sys.stdin.detach(): f.readlines(nbytes), []):
lines.sort()
file = stack.enter_context(TemporaryFile('w+b')) #NOTE: file is deleted on exit
file.writelines(uniq(lines)) # write sorted unique lines
file.seek(0) # rewind, to read later while merging partial results
sorted_files.append(file) #NOTE: do not close the temporary file, yet
# merge and write results
sys.stdout = sys.stdout.detach() # suppress ValueError: underlying buffer has
been detached
sys.stdout.writelines(uniq(heapq.merge(*sorted_files)))
Пример:
$ sort-u < emails.txt >uniq-emails.txt
В этом случае ввод принимается только со стандартного ввода и строки сравниваются
как последовательности байт (предполагается что все строки заканчиваются на символ
новой строки).
Связанный вопрос: Sorting text file by using Python.