У меня есть список ниже. Мне нужно извлечь значения времени и суммировать их в целом из приведенного ниже списка.
Значения времени могут располагаться в разных местах – например. квадратные скобки, круглая скобка, в конце строки, в начале и т.д.
Я надеялся использовать одно регулярное выражение с несколькими возможностями OR (|), чтобы пройти через каждую строку в списке и извлечь значения, чтобы иметь возможность сложить их вместе.
summary = [
"CHGnnnnnnnnn (2.5)",
"CHGnnnnnnnnn - 0.5",
"2 hours - CHGnnnnnnnnn - some random words",
"1.25 hours - CHGnnnnnnnnn - more random words",
"CHGnnnnnnnnn [2],",
"CHGnnnnnnnnn - yet more words - 2 hrs",
"CHGnnnnnnnnn, CHGnnnnnnnnn - 4hrs",
"CHGnnnnnnnnn another word- 2.5",
"1 hour - CHGnnnnnnnnn -",
"CHGnnnnnnnnn - 00552988- 3",
"CHGnnnnnnnnn(30m)",
"CHGnnnnnnnnn - more words that is not needed - 4.75"
]
Это код, который у меня есть на данный момент, который подходит только для сценариев, в которых время указывается в квадратных скобках или круглых скобках. Как только я пытаюсь свой мозг регулярных выражений включить другие строки, где время не заключено в скобки, он ломается.
import re
summary = [
"CHG453689356 (2.5)",
"CHG190394857(2.5) , CHG000159040 (3)",
"CHG098764573 [2],"
]
# Define regex pattern to extract hours
time_pattern = re.compile(r'\((\d+(\.\d*)?)\)|\[(\d+(\.\d*)?)\]')
# Initialize total hours accumulator
total_hours_all_lines = 0
# Extract and sum hours for each line
for entry in summary:
# Initialize total hours accumulator for the current line
total_hours_line = 0
# Find all matches of time pattern in the entry
time_matches = time_pattern.findall(entry)
# Iterate over matches and sum the hours for the current line
for match in time_matches:
# Check if group 0 has a valid number (for parentheses)
if match[0]:
total_hours_line += float(match[0])
# Check if group 2 has a valid number (for square brackets)
elif match[2]:
total_hours_line += float(match[2])
# Print the total hours for the current line
print(f"Total hours for line '{entry}': {total_hours_line}")
# Add the current line's total hours to the total for all lines
total_hours_all_lines += total_hours_line
# Print the total hours for all lines
print(f"Total hours for all lines: {total_hours_all_lines}")
Какие выходы:
Total hours for line 'CHG453689356 (2.5)': 2.5
Total hours for line 'CHG190394857(2.5) , CHG000159040 (3)': 5.5
Total hours for line 'CHG098764573 [2],': 2.0
Total hours for all lines: 10.0
Числовые значения времени имеют разные единицы измерения; а некоторые числа вообще не имеют единиц измерения.
Да, к сожалению, все значения времени представляют собой свободный текст, введенный людьми.






Мое предложение состояло бы в том, чтобы игнорировать проблему заключения в скобки - в любом случае не все ваши примеры содержат парные скобки любого типа - и вместо этого сосредоточиться на числах в приемлемом диапазоне.
time_matches = re.seach(r"\b\d{1,2}(?:\.\d{1,2})?(?:h(?:rs?)?|m(?:in)?)?\b", entry)
Это переключается с findall на просто search; ни один из ваших примеров не содержит более одного выражения времени.
Это все еще довольно эвристично. Если вы хотите немного ужесточить его, вы можете указать, что часы должны быть однозначными (или, по крайней мере, меньше, скажем, шестнадцати?), а минуты должны быть двузначными. Затем вы также можете разрешить часы, за которыми следуют минуты, вместо того, чтобы требовать только одно число. Но ни один из ваших примеров этого не требует, поэтому я туда не пошел.
Демо: https://regex101.com/r/yUUhGH/1
Без требования единиц измерения или строгих соглашений о форматировании невозможно справиться с такими гипотетическими записями, как
работа над проектом 2 (3)
указать 3 часа работы.
Именно из-за подобных проблем бюрократам нравятся формы, в которых вы можете предоставить только необходимую информацию в строго определенном формате. Тогда легко обрабатывать, но невозможно обрабатывать случаи, которые каким-то образом требуют специальной обработки, ручной проверки или взаимодействия.
В конце концов, если вам требуется высокая точность без проверки человеком, лучшим решением может быть система, которая требует, чтобы отправители разбивали записи на «что» и «на какой срок», где для последнего разрешен ввод только чч:мм; или, возможно, какая-то система НЛП, позволяющая попытаться понять смысл текста на основе лингвистического анализа (но даже в этом случае я не понимаю, как это может быть надежным).
Спасибо, тройное, очень ценю обратную связь. Согласен на 100%, лучшим решением было бы настроить систему захвата на точную продолжительность в универсальном формате.
Вы вообще что-нибудь пробовали? Такой сайт, как regex101.com, может стать отличным подспорьем для экспериментов — не стесняйтесь спрашивать здесь, считаете ли вы, что у вас есть что-то, что должно работать, но не работает каким-то конкретным образом. Просто отредактируйте свой вопрос и поделитесь своими попытками с описанием конкретной проблемы, с которой вы столкнулись. Кроме того, похоже, что вы предоставили некоторые образцы данных, но ваши фактические данные могут содержать символы, которые могут нарушить решение, которое будет работать в этом образце. Убедитесь, что то, чем вы делитесь, соответствует реальным данным (например, есть ли цифры в остальной части текста?)