Вы делаете это более сложным, чем это должно быть, вот откуда приходит разочарование.Реальное решение намного проще, чем вы думаете.
Словарь отслеживает свои собственные ключи.Вам не нужно ничего инициализировать.Если для буквы нет слова в словаре, вы сразу добавляете новый ключ.В противном случае вы используете список, который уже существует.
Другой момент заключается в том, что модуль string
предоставляет вам инструменты для разделения на оба whitespace
и punctuation
.Цена, которую вы платите, состоит в том, чтобы отфильтровывать некоторые пустые строки, но это тривиально.
Я бы рекомендовал хранить промежуточные результаты в set
с вместо списков, чтобы обеспечить уникальность.Вы всегда можете конвертировать в списки в качестве последнего шага.
И использовать возвращаемые значения вместо распечаток в своих служебных функциях:
def text_dictionary(file_name):
map = {}
with open(file_name,'r') as file:
for line in file:
for word in line.split(string.whitespace + string.punctuation):
if not word:
continue
word = word.lower()
if word[0] not in map:
map[word[0]] = set()
map[word[0]].add(word)
for key in map:
map[key] = list(map[key])
return map
Обратите внимание, что я не использую никаких специальных методов или атрибутовсловаря вообще кроме самого основного доступа.
Приложение 1: Преобразование словаря
Последний цикл заменяет наборы на месте списками: он несоздать новый объект словаря.Вы можете сделать то же самое с очень похожим циклом:
for key, value in map.items():
map[key] = list(item)
В общем случае вам не следует изменять словарь при его итерации по нему.Однако, если вы будете очень осторожны, касаясь только значений, а не клавиш, у вас не возникнет никаких проблем, поскольку базовая структура хеш-таблицы не изменится.
Создание словарей обходится дешево, поэтомуможет быть быстрее использовать словарь для создания нового отображения вместо этого:
map = {key: list(value) for key, value in map.items()}
Приложение 2: Разделение слов
Алгоритм разделения слов, показанный выше, чрезвычайнопросто.Предполагается, что ваш файл будет содержать только печатные символы ASCII с хорошим поведением.Хотя это, вероятно, верно для вашего задания, меня раздражает написание кода, в котором есть потенциальные проблемы, потому что будет много неизвестных проблем, которые займут ваше время позже.С этой целью я представлю несколько альтернативных способов поиска слов с использованием регулярных выражений .
Первая альтернатива - разделить на что-нибудь, что не 'т слово характер.Символ слова (в обычной строке) соответствует шаблону \w
, который
Соответствует символам слова Unicode;это включает в себя большинство символов, которые могут быть частью слова на любом языке, а также цифры и подчеркивание.Если используется флаг ASCII , сопоставляется только [a-zA-Z0-9_]
.
Обратное значение \w
равно \W
, поэтому вы можете использовать его с re.split
:
for word in re.split(r'\W+', line):
Второй вариант - дополнение к первому.Вместо разделения на шаблон, сопоставьте шаблон и используйте re.finditer
, чтобы составить список слов для вас:
for word in re.finditer(r'\w+', line):
Я в обоих случаях, этоСтоит отметить, что вам лучше предварительно скомпилировать выбранный шаблон, используя re.compile
вместо того, чтобы каждый раз перекомпилировать шаблон.Наиболее эффективный способ установить шаблон - это либо глобально, либо с помощью аргумента функции по умолчанию.Таким образом, он будет оценен только один раз.Второй лучший вариант - сделать это перед блоком with
, чтобы вы по крайней мере компилировали один раз для файла, а не для каждой строки.Глобальное или функциональное определение будет выглядеть как
pattern = re.compile(r'\w') # or r'\W', as you prefer
В качестве аргумента по умолчанию:
def text_dictionary(file_name, pattern=re.compile(r'\w')):
Последний подход дает вам гибкость, если вы когда-нибудь решите изменить набор символов
В любом случае цикл будет
for word in pattern.split(line): # or pattern.finditer(line)