Я пытался найти эффективное решение для следующей проблемы. У меня есть отсортированный список слов, содержащих диакритические знаки, и я хочу иметь возможность выполнять поиск без использования диакритики. Так, например, я хочу сопоставить «kříž», просто используя «kriz». После небольшого мозгового штурма я придумал следующее, и я хочу спросить вас, более опытные (или умные), оптимально ли это или есть лучшее решение. Я использую Python, но проблема не зависит от языка.Поиск слов без диакритики в отсортированном списке слов
Сначала я предоставляю сопоставление тех персонажей, которые имеют несколько диакритических братьев и сестер. Поэтому в случае чешского языка:
cz_map = {'a' : ('á',), ... 'e' : ('é', 'ě') ... }
Теперь я могу легко создать все варианты слова на входе. Поэтому для «ламы» я получаю: ['lama', 'láma', 'lamá', 'lámá']. Я уже мог использовать это для поиска слов, которые соответствуют любой из этих перестановок, но когда дело доходит до таких слов, как «непредвидательный» (непредсказуемый), получается 13824 перестановки. Несмотря на то, что у моего ноутбука яркий логотип Intel i5 на нем, это на мой вкус слишком наивное решение.
Вот улучшение, которое я придумал. Словарь слов, которые я использую, имеет вариант бинарного поиска для сопоставления префикса (возвращает слово в нижнем индексе с соответствующим префиксом), что очень полезно в этом случае. Я начинаю с первого символа, ища его префикс существования в словаре, и если он есть, я складываю его для следующего символа, который будет протестирован, добавленный ко всем этим сложным последовательностям. Таким образом, я распространяю только те строки, которые приводят к совпадению. Вот код:
def dia_search(word, cmap, dictionary):
prefixes = ['']
for c in word:
# each character maps to itself
subchars = [c]
# and some diacritical siblings if they exist
if cmap.has_key(c):
subchars += cmap[c]
# build a list of matching prefixes for the next round
prefixes = [p+s for s in subchars
for p in prefixes
if dictionary.psearch(p+s)>0]
return prefixes
Этот метод дает очень хорошие результаты, но может быть еще лучше? Или есть метод, который не нуждается в сопоставлении символов, как в этом случае? Я не уверен, что это актуально, но словарь, который я использую, не сортируется никакими правилами сортировки, поэтому последовательность - это «a», «z», «a», «a», «á», «z», как и следовало ожидать.
Спасибо за комментарии.
EDIT: Я не могу создать вспомогательную предварительно вычисленную базу данных, которая была бы копией оригинала, но без диакритики. Предположим, что исходная база данных слишком велика для тиражирования.
Это может быть использовано для создания копии моего списка слов без диакритики. Дело в том, что я не могу хранить две копии, только оригинальную с диакритикой. Если у вас есть база данных, содержащая 3 миллиона элементов, то дублирование это не путь. – plebuch
в какой-то момент вам нужно сделать это (или аналогичный) перевод. будь то создание индекса в базе данных или что-то еще ... 'translate' должен быть более эффективным, чем просто использовать' dict'. (3 миллиона элементов в db должны быть отлично обрабатываемыми). –
В какой момент вы имеете в виду? Я представил решение, которое работает с оригинальной копией, и мой вопрос был: есть ли что-нибудь более эффективное? Дублирование базы данных размером в сотни МБ - это то, что я не вижу более эффективным. Еще один недостаток «перевести» - это не позволяет мне отображать немецкий «ß» в «ss», или это будет? Во всяком случае, 'translate' vs' dict' на самом деле не очень уместен, потому что он используется только для того, чтобы удерживать отображение, которое составляет всего несколько символов почти в каждом алфавите, использующем латинский язык. В случае чешского языка это всего лишь 15 диакритических символов, которые необходимо сопоставить. – plebuch