У меня есть строки, содержащие разные значения (числовые и нечисловые смешанные). Я хочу иметь возможность извлекать значения из текста. Я не мог понять, как извлечь все (или большинство) возможных случаев. У меня есть частично работающее решение, подобное этому,
def extract_values(sentence):
#sentence = normalizeString(sentence)
matches = re.findall(r'((\d*\.?\d+(?:\/\d*\.?\d+)?)(?:\s+and\s+(\d*\.?\d+(?:\/\d*\.?\d+)?))?)', sentence)
# (\d\sto\s\d\s(and\s\d\/\d)*) << for adding 9 to 11, couldn't fix
result = []
for x,y,z in matches:
if '/' in x:
result.append(x)
else:
result.extend(filter(lambda x: x!="", [y,z]))
return result
Код водителя,
extract_values("He is 1 and 1/2 years old. He is .5 years old and he is 5 years old. He is between 9 to 11 or 9 to 9 and 1/2. He was born 11/12/20")
Неправильный ответ:
['1 and 1/2', '5', '5', '9', '11', '9', '9 and 1/2', '11/12', '20']
Ожидаемый ответ:
['1 and 1/2', '.5', '5', '9 to 11', '9 to 9 and 1/2', '11/12/20']
Обратите внимание на разницу между 5 и .5, а также между «x и y» и «x в y и z».
Буду признателен за любую помощь. Спасибо.
2 ответа
Ты можешь использовать
import re
def extract_values(sentence):
num = r'\d*\.?\d+(?:/\d*\.?\d+)*'
return re.findall(fr'{num}(?:\s+(?:and|to)\s+{num})*', sentence)
print(extract_values("He is 1 and 1/2 years old. He is .5 years old and he is 5 years old. He is between 9 to 11 or 9 to 9 and 1/2. He was born 11/12/20"))
# => ['1 and 1/2', '.5', '5', '9 to 11', '9 to 9 and 1/2', '11/12/20']
См. демонстрацию Python и демонстрация регулярного выражения.
Подробности :
\d*\.?\d+(?:/\d*\.?\d+)*
- число с плавающей запятой/целое число, а затем ноль или более вхождений/
и число с плавающей запятой/целое число(?:\s+(?:and|to)\s+\d*\.?\d+(?:/\d*\.?\d+)*)*
- ноль или более вхождений <ул>\s+(?:and|to)\s+
–and
илиto
, заключенные в один или несколько пробелов\d*\.?\d+(?:/\d*\.?\d+)*
– число с плавающей запятой/целое число, а затем ноль или более вхождений/
и число с плавающей запятой/целое число.
Я бы сделал это следующим образом
import re
text = "He is 1 and 1/2 years old. He is .5 years old and he is 5 years old. He is between 9 to 11 or 9 to 9 and 1/2. He was born 11/12/20"
values = re.findall(r"\d+(?:\s?(?:and|/|to)\s?\d+)*",text)
print(values)
Выход
['1 and 1/2', '5', '5', '9 to 11', '9 to 9 and 1/2', '11/12/20']
Объяснение: здесь я использовал незахватывающую группу. Этот шаблон ищет 1 или более цифр, за которыми следует (and
или /
или to
, возможно, с начальным и/или конечным пробелом, за которым следует 1 или более цифр), повторяющихся ноль или более раз.
Если вы хотите включить .
в начале, вы можете добавить \.?
к моему шаблону.
.5
, вы можете предварительно добавить необязательную \.
(буквальную точку) к моему шаблону, чтобы она стала r"\.?\d+(?:\s?(?:and|/|to)\s?\d+)*"
, и тогда вывод будет r"\.?\d+(?:\s?(?:and|/|to)\s?\d+)*"
['1 and 1/2', '.5', '5', '9 to 11', '9 to 9 and 1/2', '11/12/20']
Похожие вопросы
Новые вопросы
python
Python — это мультипарадигмальный многоцелевой язык программирования с динамической типизацией. Он предназначен для быстрого изучения, понимания и использования, а также обеспечивает чистый и унифицированный синтаксис. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Если у вас есть вопросы о версии Python, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas, NumPy) укажите это в тегах.
and
на(and|to)
?/
char? Посмотрите на решение ниже, пожалуйста, оставьте отзыв. Пожалуйста, добавьте к вопросу требования к шаблону/логику сопоставления..5
с ответом @Daweo с помощью небольшого улучшения, например вот так .