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

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».

Буду признателен за любую помощь. Спасибо.

3
Droid-Bird 23 Дек 2021 в 16:34
Пробовали заменить and на (and|to)?
 – 
TheMaster
23 Дек 2021 в 16:41
Вам действительно нужно проверить значение группы 1 для / char? Посмотрите на решение ниже, пожалуйста, оставьте отзыв. Пожалуйста, добавьте к вопросу требования к шаблону/логику сопоставления.
 – 
Wiktor Stribiżew
23 Дек 2021 в 16:51
Вы можете поймать .5 с ответом @Daweo с помощью небольшого улучшения, например вот так .
 – 
bobble bubble
23 Дек 2021 в 18:08
Принимая во внимание ваш предыдущий вопрос, я считаю, что вам нужен ideone.com/VG2qKH. Или вам нужно другое решение сейчас?
 – 
Wiktor Stribiżew
23 Дек 2021 в 20:22

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+)* – число с плавающей запятой/целое число, а затем ноль или более вхождений / и число с плавающей запятой/целое число.
1
Wiktor Stribiżew 23 Дек 2021 в 20:30

Я бы сделал это следующим образом

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 или более цифр), повторяющихся ноль или более раз.

Если вы хотите включить . в начале, вы можете добавить \.? к моему шаблону.

1
Daweo 24 Дек 2021 в 11:29
1
Большое Вам спасибо. Выглядит многообещающе. Проблема, которую я вижу, в том, что 0,5 (или 0,5) здесь не отражены. Любая идея?
 – 
Droid-Bird
23 Дек 2021 в 19:19
@Droid-Bird относительно начальной точки, как в .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']
 – 
Daweo
23 Дек 2021 в 21:46
Я нечаянно проголосовал. Пожалуйста, внесите небольшое редактирование, чтобы я мог исправить свою ошибку (и оставьте сообщение, информирующее меня о том, что вы это сделали).
 – 
Cary Swoveland
24 Дек 2021 в 00:48