Сопоставление строки с набором ключевых слов, связанных с ключом

#python

#python

Вопрос:

Допустим, у меня есть список текстовых файлов (текстов песен) для возврата на основе пользовательского ввода:

 song_1.txt
song_2.txt
...
song_n.txt
  

Мне не нравится идея перечисления их всех сразу, чтобы пользователь мог выбирать, поэтому моей первоначальной мыслью было создать простую функцию, которая принимает ввод пользователя в качестве аргумента, выполняет поиск по списку предопределенных ключевых слов для каждой песни и возвращает «наиболее подходящую песню»в качестве ответа.

Я довольно новичок в python и программировании в целом, и лучшее, что я мог придумать до сих пор, это что-то вроде этого:

 keywords = {'song_1': ['hate', 'bad'], 'song_2': ['love', 'good']}

def find_song_by_keyword(user_input):
    for song, keyword in keywords.items():
        if user_input in keyword:
            return song   '.txt'


result = find_song_by_keyword('love')
print(result)
  
 song_2.txt
  

Затем я собираюсь прочитать песню из файла и вернуть ее пользователю, но мой вопрос:

  • Каков наилучший способ сопоставить строку с ключевыми словами, учитывая тот факт, что мне нужно отследить «ключ»? У меня такое чувство, что есть лучшее решение для сопоставления чего-либо с ключевыми словами вместо использования for loop dictionary со списком в качестве значения. Просто ищу некоторые указания по этому вопросу в целом (я был бы признателен за ссылку на что-то, связанное с «поиском» в целом, возможно, что-то более глубокое).

Комментарии:

1. Инвертируйте словарь и сопоставьте ключевые слова с песнями. {'hate': 'song_1', 'bad': 'song_1', 'love': 'song_2', 'good': 'song_2'} . Тогда вы можете просто получить keywords.get(user_input)

2. @Barmar — Не будут ли здесь проблемы с дублирующими ключами?

3. Цикл находит только одну песню для каждого ключевого слова, поэтому дубликаты игнорируются.

Ответ №1:

В использовании a for -loop нет ничего плохого, тем более, что вы завершаете работу, когда находите первое совпадение, и, похоже, это то, что вам нужно.

Однако вы также можете получить ключ таким образом:

 result = next((song for song, words in keywords.items() if 'love' in words), None)
  

Или, если вы не хотите повторяться, и вам нужно использовать это в нескольких местах, просто оберните это в определение функции, конечно:

 def find_song_by_keyword(user_input):
    return next((song for song, words in keywords.items() if user_input in words), None)


result = find_song_by_keyword('love')
  

Такие решения, как инвертирование словаря, могут быть хорошей идеей, если вам приходится делать это очень часто, поскольку вы обмениваете пространство для повышения производительности, но, конечно, действие инвертирования также занимает некоторое время, поэтому, похоже, оно не очень хорошо соответствует вашему варианту использования.

Пользователь @Barmar верно отмечает, что исходный словарь может быть создан как словарь «поисковый запрос -> имя файла» вместо текущего «имя файла -> поисковый запрос». Вероятно, вы могли бы создать словарь с поисковыми терминами в качестве ключей примерно так же, как вы создаете текущий словарь, в зависимости от того, как вы планируете его создавать.

Комментарии:

1. Вам нужно только один раз инвертировать словарь при его создании, а не при каждом поиске.

2. Конечно, но вам нужно инвертировать весь словарь, а затем обращаться к инвертированному словарю для каждого поиска, что является более дорогостоящей операцией, чем поиск по оригиналу несколько раз. (помимо потенциальной потери некоторой информации, но это выходит далеко за рамки вопроса OP)

3. Словарь должен создаваться и обновляться в инвертированном режиме.