Вы должны делать все это лениво и с как можно меньшим количеством промежуточных списков и, насколько это возможно (сокращение алкаций и времени обработки).Все уникальные слова из файла:
import itertools
def unique_words_from_file(fpath):
with open(fpath, "r") as f:
return set(itertools.chain.from_iterable(map(str.split, f)))
Позволяет объяснить идеи здесь.
Файловые объекты являются итеративными объектами, это означает, что вы можете перебирать строки файла!
Тогда нам нужны слова из каждой строки, которые разбивают их.В этом случае мы используем map
в Python3
(или itertools.imap
в Python2
) для создания объекта с таким вычислением по строкам нашего файла.map
и imap
также ленивы, это означает, что промежуточный список не выделяется по умолчанию, и это здорово, потому что мы не будем тратить ресурсы на то, что нам не нужно!
Так как str.split
возвращает список, наш map
результат будет последовательностью списков строк, но нам нужно перебрать каждую из этих строк.Для этого не нужно создавать еще один list
, мы можем использовать itertools.chain
, чтобы сгладить этот результат!
Наконец, мы вызываем set, который будет перебирать эти слова и сохранять только одно длякаждый из них.Вуаля!
Давайте сделаем улучшение !, можем ли мы сделать str.split
ленивым? Да!отметьте SO ответ :
import itertools
import re
def split_iter(string):
return (x.group(0) for x in re.finditer(r"[A-Za-z']+", string))
def unique_words_from_file(fpath):
with open(fpath, "r") as f:
return set(itertools.chain.from_iterable(map(split_iter, f)))