Как проверить, существует ли слово или группа слов в заданном списке строк и как извлечь это слово?

#python #string #list #dictionary

#python #строка #Список #словарь

Вопрос:

У меня есть список строк следующим образом :

 list_of_words = ['all saints church','churchill college', "great saint mary's church", 'holy trinity church', "little saint mary's church", 'emmanuel college']
 

И у меня есть список словарей, который содержит «текст» в качестве ключа и предложение в качестве значения. Это выглядит следующим образом :

     "dict_sentences": [
    {
        "text": "Can you help me book a taxi going from emmanuel college to churchill college?"
    },
    {
        "text": "Yes, I could! What time would you like to depart from Emmanuel College?"
    },
    {
        "text": "I want a taxi to holy trinity church"
    },
    {
        "text": "Alright! I have a yellow Lexus booked to pick you up. The Contact number is 07543493643. Anything else I can help with?"
    },
    {
        "text": "No, that is everything I needed. Thank you!"
    },
    {
        "text": "Thank you! Have a great day!"
    }
]
 

Для каждого предложения в dict_sentences я хочу проверить, существует ли в этом предложении какое-либо из слов из list_of_words, и если да, я хочу сохранить его в другом словаре (так как мне нужно еще поработать над ним).

Например, в первом предложении в dict_sentences: «Не могли бы вы помочь мне заказать такси, идущее от колледжа Эммануэля до колледжа Черчилля?«, подстрока «колледж Черчилля» и «колледж Эммануэля» существует в нашем list_of_words, поэтому я хочу сохранить слова «колледж Черчилля» и «колледж Эммануэля» в другом словаре, например { sent1 : ['churchill college', 'emmanuel college'] }

Таким образом, ожидаемый результат будет :

 {  sent1 : ['churchill college', 'emmanuel college'] ,
   sent2 : [ 'emmanuel college' ],
   sent3 : [ 'holy trinity church' ]
} # ignore the rest of sentences as no word from list_of_words exist in them
 

Основная проблема здесь заключается в проверке, состоит ли данное предложение из слова / группы слов (например, «церковь святой Троицы» — 3 слова) в данном предложении, и если да, извлекает то же самое. Я просмотрел другие ответы, и был предложен следующий код для проверки, встречается ли слово из списка в предложении :

 if any(word in sentence for word in list_of_words()): 
     pass
 

Однако таким образом мы можем только проверить, существует ли слово из предложения в list_of_words() , чтобы извлечь слово, мне придется запускать циклы for . Но я воздерживаюсь от использования циклов for, поскольку мне нужно очень экономичное по времени решение, потому что у меня около 300 документов, где каждый документ состоит из таких 10-15 (или более) предложений, а list_of_words слишком велик, т.Е. около 300 строк. Итак, мне нужен эффективный по времени способ проверки и извлечения слова из заданного предложения, которое существует в list_of_words .

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

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

Ответ №1:

Вы могли бы использовать re.findall so, чтобы не было вложенного цикла.

 output = {}
find_words = re.compile('|'.join(list_of_words)).findall
for i, (s,) in enumerate(map(dict.values, data['dict_sentences']), 1):
    words = find_words(s.lower())
    if words:
        output[f"sent{i}"] = words
 

 {'sent1': ['emmanuel college', 'churchill college'],
 'sent2': ['emmanuel college'],
 'sent3': ['holy trinity church']}
 

Это также можно сделать в dict_comprehension, используя оператор walrus в python 3.8 , хотя это может быть немного чрезмерно:

 find_sent = re.compile('|'.join(list_of_words)).findall
iter_sent = enumerate(map(dict.values, data['dict_sentences']), 1)
output = {f"sent{i}": words for i, (s,) in iter_sent if (words := find_sent(s.lower()))}
 

Ответ №2:

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

 test = {"dict_sentences":...} # I'm assuming it's a section of a json or a larger dictionary.

output = {}
j = 1
for sent in test["dict_sentences"]:
    addition = []
    for i in list_of_words:
        if i.upper() in sent["text"].upper():
            addition.append(i)
    if addition:
        output[f"sent{j}"] = addition
        j  = 1
 

Ответ №3:

Вы можете выполнить понимание вложенного dict и сравнить содержимое, преобразовав оба в нижний регистр, например:

 
output = {
    f"sent{i 1}": [
        phrase for phrase in list_of_words if phrase.lower() in sentence['text'].lower()
    ] for i,sentence in enumerate(dict_sentences)
}

output_without_empty_matches = { k:v for k,v in output.items() if v }

print(output_without_empty_matches)
>>> {'sent1': ['churchill college', 'emmanuel college'], 'sent2': ['emmanuel college'], 'sent3': ['holy trinity church']}
 

Ответ №4:

 new_list=[]
new_dict={}

for index, subdict in enumerate(dict_sentences):
    for word in list_of_words:
        if word in subdict['text'].lower():
            key="sent" str(index 1)
            new_list.append(word)
            new_dict[key]=new_list
    new_list=[]

print(new_dict)