Это был вопрос, который я получил во время собеседования с технической фирмой, и я думаю, что в конечном итоге это убило мои шансы.
Вам дано предложение и словарь, в котором слова являются ключами, а части речи — значениями.
Цель состоит в том, чтобы написать функцию, в которой, когда вам дано предложение, каждое слово заменяется на его часть речи, указанную в словаре, по порядку. Мы можем предположить, что все слова в предложении присутствуют как ключи в словаре.
Например, предположим, что нам даны следующие входные данные:
sentence='I am done; Look at that, cat!'
dictionary = {'!': 'sentinel', ',': 'sentinel',
'I': 'pronoun', 'am': 'verb',
'Look': 'verb', 'that': 'pronoun',
'at': 'preposition', ';': 'preposition',
'done': 'verb', ',': 'sentinel',
'cat': 'noun', '!': 'sentinel'}
output='pronoun verb verb sentinel verb preposition pronoun sentinel noun sentinel'
Сложность заключалась в том, чтобы поймать стражников. Если в части речи не было часовых, это можно легко сделать. Есть ли простой способ сделать это? Любая библиотека?
Пакет Python Регулярное выражение можно использовать для разделения предложения на токены.
import re
sentence='I am done; Look at that, cat!'
dictionary = {'!': 'sentinel', ',': 'sentinel',
'I': 'pronoun', 'am': 'verb',
'Look': 'verb', 'that': 'pronoun',
'at': 'preposition', ';': 'preposition',
'done': 'verb', ',': 'sentinel',
'cat': 'noun', '!': 'sentinel'}
tags = list()
for word in re.findall(r"[A-Za-z]+|\S", sentence):
tags.append(dictionary[word])
print (' '.join(tags))
Выход
pronoun verb verb preposition verb preposition pronoun sentinel noun sentinel
Регулярное выражение [A-Za-z]+|\S
в основном выбирает все алфавиты (заглавные и строчные) с одним или несколькими их вхождениями с помощью [A-Za-z]+
, а также (выполнено с помощью |
, что означает изменение) все небелые пробелы с помощью \s
.
@user98235 user98235 Объяснено в самом ответе.
Это регулярное выражение. Регулярное выражение — это специальная текстовая строка для описания шаблона поиска. Вы можете думать о регулярных выражениях как о подстановочных знаках на стероидах.
Вот менее впечатляющее, но более понятное решение:
Давайте начнем с определения примера словаря и предложения в вашем вопросе:
sentence = 'I am done; Look at that, cat!'
dictionary = {
'!': 'sentinel',
',': 'sentinel',
',': 'sentinel',
'I': 'pronoun',
'that': 'pronoun',
'cat': 'noun',
'am': 'verb',
'Look': 'verb',
'done': 'verb',
'at': 'preposition',
';': 'preposition',
}
Для моего решения я определяю функцию рекурсивного синтаксического анализа с метким названием parse
.
parse
сначала разбивает предложение на слова пробелами, затем пытается классифицировать каждое слово, ища его в предоставленном словаре.
Если слово не может быть найдено в словаре (потому что к нему прикреплены какие-то знаки препинания и т. д.), parse
затем разбивает слово на составные токены и рекурсивно анализирует его оттуда.
def parse(sentence, dictionary):
# split the words apart by whitespace
# some tokens may still be stuck together. (i.e. "that,")
words = sentence.split()
# this is a list of strings containing the 'category' of each word
output = []
for word in words:
if word in dictionary:
# base case, the word is in the dictionary
output.append(dictionary[word])
else:
# recursive case, the word still has tokens attached
# get all the tokens in the word
tokens = [key for key in dictionary.keys() if key in word]
# sort all the tokens by length - this makes sure big words are more likely to be preserved. (scat -> s, cat or sc, at) check
tokens.sort(key=len)
# this is where we'll store the output
sub_output = None
# iterate through the tokens to find if there's a valid way to split the word
for token in tokens:
try:
# pad the tokens inside each word
sub_output = parse(
word.replace(token, f" {token} "),
dictionary
)
# if the word is parsable, no need to try other combinations
break
except:
pass # the word couldn't be split
# make sure that the word was split - if it wasn't it's not a valid word and the sentence can't be parsed
assert sub_output is not None
output.append(sub_output)
# put it all together into a neat little string
return ' '.join(output)
Вот как вы будете его использовать:
# usage of parse
output = parse(sentence, dictionary)
# display the example output
print(output)
Я надеюсь, что мой ответ дал вам больше информации о другом методе, который можно использовать для решения этой проблемы.
Тада! ?
Если вы ищете подход, основанный не на регулярных выражениях, вы можете попробовать следующее:
def tag_pos(sentence):
output = []
for word in sentence.split():
if word not in dictionary:
literal = ''.join([char for char in word if not char.isalpha()])
word = ''.join([char for char in word if char.isalpha()])
output.append(dictionary[word])
if not len(literal)>1:
output.append(dictionary[literal])
else:
for literal in other:
output.append(dictionary[literal])
else:
output.append(dictionary[word])
return " ".join(output)
output = tag_pos(sentence)
print(output)
"[A-Za-z]+|\S" <-- что он делает?