Проверка наличия слов в предложении

#python #utf-8

#python #utf-8

Вопрос:

Я пишу программу на Python. Пользователь вводит текстовое сообщение. Необходимо проверить, есть ли в этом сообщении последовательность слов. Пример. Сообщение: «Привет, мир, мой друг».. Проверьте последовательность этих двух слов: «Привет», «мир». Результат «True». Но при проверке последовательности этих слов в сообщении: «Привет, прекрасный мир» результатом является «false». Когда вам нужно проверить наличие только двух слов, это возможно, как я сделал это в коде, но когда комбинации из 5 или более слов затруднены. Есть ли какое-нибудь небольшое решение этой проблемы?

 s=message.text
s=s.lower()
lst = s.split()
elif "hello" in lst and "world" in lst :
    if "hello" in lst:
        c=lst.index("hello")
    if lst[c 1]=="world" or lst[c-1]=="world":
        E=True
    else:
        E=False
  

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

1. Если вы разделите "hello, beautiful world" на список, список будет содержать "hello," , а не "hello" .

2. Вы также хотите, чтобы «world hello» возвращало значение true? Если есть 5 слов, могут ли они располагаться в любом порядке?

3. @Matthias Да, но если сообщение будет таким: «Мир, как дела? Всем привет.» Моя программа вполне рабочая для такого случая, но если вам нужно найти последовательно стоящие, но в любом порядке 5 слов?…

4. Уберите знаки препинания перед разделением, и вы, вероятно, захотите свести все к одному регистру (например, lower() ).

5. @Alex Да, они могут располагаться в любом порядке, но последовательно, т.е. между ними нет других слов. «привет», «мой», «дорогой», «друг», «Дима» или «мой», «дорогой», «друг», «Дима», «привет» или другие варианты.

Ответ №1:

Самый простой способ — использовать цикл. Разделите ваше сообщение на отдельные слова, а затем проверьте наличие каждого из них в предложении в целом.

 word_list = message.split()     # this gives you a list of words to find
word_found = True
for word in word_list:
    if word not in message2:
        word_found = False

print(word_found)
  

Флаг word_found равен True , если в предложении были найдены все слова. Есть много способов сделать это короче и быстрее, особенно с использованием all оператора и предоставления списка слов в виде встроенного выражения.

 word_found = all(word in message2 for word in message.split())
  

Теперь, если вам нужно ограничить ваше свойство «найдено» точным соответствием слов, вам потребуется дополнительная предварительная обработка. Приведенный выше код слишком снисходителен к подстрокам, например, поиск «Ты в порядке?» в предложении «твоя шутка едва ли смешна». Для более строгого регистра вам следует разбить message2 на слова, убрать из этих слов знаки препинания, перевести их в нижний регистр (чтобы упростить сопоставление), а затем искать каждое слово (из message ) в списке слов из message2 .

Можете ли вы извлечь это оттуда?

Ответ №2:

Сначала я уточню ваше требование:

  • игнорировать регистр

  • последовательная последовательность

  • совпадение в любом порядке, например, перестановка или анаграмма

  • поддержка дублированных слов

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

  1. разделить все слова в текстовом сообщении
  2. соедините их с ' '
  3. перечислите все перестановки слов и соедините их с ' ' too, например, если вы хотите проверить последовательность ['Hello', 'beautiful', 'world'] . Перестановка будет 'Hello beautiful world' , 'Hello world beautiful' , 'beautiful Hello world' … и так далее.
  4. и вы можете просто найти, есть ли в нем одна такая перестановка, как 'hello beautiful world' .

Пример кода находится здесь:

 import itertools
import re

# permutations brute-force, O(nk!)
def checkWords(text, word_list):
    # split all words without space and punctuation
    text_words= re.findall(r"[w'] ", text.lower())

    # list all the permutations of word_list, and match
    for words in itertools.permutations(word_list):
        if ' '.join(words).lower() in ' '.join(text_words):
            return True
    return False

    # or use any, just one line
    # return any(' '.join(words).lower() in ' '.join(text_words) for words in list(itertools.permutations(word_list)))
def test():
    # True
    print(checkWords('Hello world, my friend.', ['Hello', 'world', 'my']))
    # False
    print(checkWords('Hello, beautiful world', ['Hello', 'world']))
    # True
    print(checkWords('Hello, beautiful world Hello World', ['Hello', 'world', 'beautiful']))
    # True
    print(checkWords('Hello, beautiful world Hello World', ['Hello', 'world', 'world']))
  

Но это дорого обходится, когда количество слов велико, k слов сгенерируют k! перестановку, временная сложность равна O (nk!).

Я думаю, что более эффективным решением является sliding window . Временная сложность уменьшится до O (n):

 import itertools
import re
import collections

# sliding window, O(n)
def checkWords(text, word_list):
    # split all words without space and punctuation
    text_words = re.findall(r"[w'] ", text.lower())
    counter = collections.Counter(map(str.lower, word_list))
    start, end, count, all_indexes = 0, 0, len(word_list), []

    while end < len(text_words):
        counter[text_words[end]] -= 1
        if counter[text_words[end]] >= 0:
            count -= 1
        end  = 1

        # if you want all the index of match, you can change here
        if count == 0:
            # all_indexes.append(start)
            return True

        if end - start == len(word_list):
            counter[text_words[start]]  = 1
            if counter[text_words[start]] > 0:
                count  = 1
            start  = 1

    # return all_indexes
    return False
  

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

1. Это хорошее начало. Следует точно указать, какие символы разрешено содержать искомому слову с помощью этого кода. Также необходимо обобщить, чтобы находить искомые слова в любом порядке (но все равно вместе).

2. Хорошо, но мне также нужно, чтобы ответ «привет из мира» был правдивым. И если слов 3, то любая комбинация из этих слов. Должен ли я использовать «перестановки» для этого?

3. извините, я неправильно понял с первого раза, вы можете посмотреть, соответствует ли новая версия тому, что вам нужно @Человек с вопросом

4. Спасибо. Это то, что мне нужно.

5. Пожалуйста, и это дорого стоит, когда количество слов увеличивается, это генерирует K! перестановку. Возможно, позже я обновлю более эффективный способ. @Человек с вопросом

Ответ №3:

Я не знаю, действительно ли это то, что вам нужно, но это сработало, вы можете протестировать

 message= 'hello world'
message2= ' hello beautiful world' 
if 'hello' in message and 'world'  in message :
  print('yes')
else :
  print('no')
if   'hello' in message2 and 'world'  in message2 :
  print('yes')  
  

out поместить :
да
да

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

1. Слова должны последовательно обсуждаться. Для параметра «привет, прекрасный мир» результатом должно быть «Нет».