Ответ 1
Я бы, вероятно, подошел к этому как задача chunking и использовал nltk
часть речевого метки в сочетании с регулярным выражением chunker. Это позволит вам определить регулярное выражение, основанное на части речи слов в ваших предложениях, а не на самих словах. Для данного предложения вы можете сделать следующее:
import nltk
# example sentence
sent = 'send me a table with a price greater than $100'
Первое, что я хотел бы сделать, это немного изменить ваши предложения, чтобы вы не слишком сильно путали часть речевого метки. Вот несколько примеров изменений, которые вы можете сделать (с очень простыми регулярными выражениями), но вы можете поэкспериментировать и посмотреть, есть ли другие:
$10 -> 10 dollars
200lbs -> 200 lbs
5-7 -> 5 - 7 OR 5 to 7
поэтому получаем:
sent = 'send me a table with a price greater than 100 dollars'
теперь вы можете получить части речи из своего предложения:
sent_pos = nltk.pos_tag(sent.split())
print(sent_pos)
[('send', 'VB'), ('me', 'PRP'), ('a', 'DT'), ('table', 'NN'), ('with', 'IN'), ('a', 'DT'), ('price', 'NN'), ('greater', 'JJR'), ('than', 'IN'), ('100', 'CD'), ('dollars', 'NNS')]
Теперь мы можем создать chunker, который будет обрезать ваш тег с тегами POS в соответствии с (относительно) простым регулярным выражением:
grammar = 'NumericalPhrase: {<NN|NNS>?<RB>?<JJR><IN><CD><NN|NNS>?}'
parser = nltk.RegexpParser(grammar)
Этот параметр определяет синтаксический анализатор с грамматикой, которая разбивает числовые фразы (что мы будем называть вашим типом фразы). Он определяет вашу цифровую фразу как: необязательное существительное, за которым следует необязательное наречие, за которым следует сравнительное прилагательное, предлог, число и необязательное существительное. Это всего лишь предложение о том, как вы можете определить свои фразы, но я думаю, что это будет намного проще, чем использование регулярного выражения для самих слов.
Чтобы получить свои фразы, вы можете:
print(parser.parse(sent_pos))
(S
send/VB
me/PRP
a/DT
table/NN
with/IN
a/DT
(NumericalPhrase price/NN greater/JJR than/IN 100/CD dollars/NNS))
Или получить только свои фразы, которые вы можете сделать:
print([tree.leaves() for tree in parser.parse(sent_pos).subtrees() if tree.label() == 'NumericalPhrase'])
[[('price', 'NN'),
('greater', 'JJR'),
('than', 'IN'),
('100', 'CD'),
('dollars', 'NNS')]]