#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:
Сначала я уточню ваше требование:
-
игнорировать регистр
-
последовательная последовательность
-
совпадение в любом порядке, например, перестановка или анаграмма
-
поддержка дублированных слов
если число не слишком велико, вы можете попробовать этот простой для понимания, но не самый быстрый способ.
- разделить все слова в текстовом сообщении
- соедините их с
' '
- перечислите все перестановки слов и соедините их с
' '
too, например, если вы хотите проверить последовательность['Hello', 'beautiful', 'world']
. Перестановка будет'Hello beautiful world'
,'Hello world beautiful'
,'beautiful Hello world'
… и так далее. - и вы можете просто найти, есть ли в нем одна такая перестановка, как
'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. Слова должны последовательно обсуждаться. Для параметра «привет, прекрасный мир» результатом должно быть «Нет».