Регулярное выражение для интерпретации неудобной научной записи

Хорошо, я работаю с этими ENDF данными, см. здесь. Иногда в файлах присутствует, пожалуй, самая раздражающая кодировка чисел с плавающей запятой в научной записи, которую я когда-либо видел1. Там часто употребляется, что вместо 1.234e-3 будет что-то вроде 1.234-3 (без «е»).

Теперь я видел библиотеку, которая просто меняет - на e- или + на e+ простой заменой. Но это не работает, когда некоторые числа могут быть отрицательными. В конечном итоге вы получаете какую-то ерунду, например, e-5.122e-5, когда на входе было -5.122-5.

Итак, я думаю, мне нужно перейти к регулярному выражению? Я открыт для другого решения, более простого, но это лучшее, что я могу сейчас придумать. Я использую библиотеку re Python. Я могу сделать простую замену, ищу [0-9]-[0-9] и заменяю ее следующим образом:

import re
str1='-5.634-5'
x = re.sub('[0-9]-[0-9]','4e-5',str1)
print(x)

Но, очевидно, в целом это не сработает, потому что мне нужно, чтобы цифры до и после - были такими, какими они были, а не просто тем, что я придумал... Раньше я использовал группы захвата, но это было бы самым быстрым способом в этот контекст, чтобы использовать группу захвата для цифр до и после - и передать ее обратно в замену с помощью библиотеки регулярных выражений Pythonimport re?

1 Да, я знаю, фортран... 80 символов... экономия места... перфокарты... уже никого не волнует.

Работает ли у вас утверждение ретроспективного просмотра? re.sub('(?<=[0-9])-','e-',str1)

dROOOze 30.07.2024 22:57

Если вы хотите знать, что быстрее, просто измерьте их (т. е. засеките время).

Diego Torres Milano 30.07.2024 22:59

...80 символов... уже никого не волнует. - Вы серьезно думаете, что пластинки фиксированной длины остались в прошлом?

Woodford 31.07.2024 00:45

Существует пакет pip под названием endf, который, вероятно, подойдет для ваших целей.

import random 31.07.2024 02:20

@Woodford Я думаю, что они осуждают отсутствие при сохранении символов подразумеваемой e в 1.234-5, чтобы помочь соблюдать ограничение в 80 символов, а не записи фиксированной длины.

import random 31.07.2024 02:26
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
5
79
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Вероятно, для этого не будет использоваться регулярное выражение, когда должны работать некоторые простые строковые операции:

s.replace("-", "e-").replace("+", "e+").lstrip("e")

Я бы пошел на что-нибудь в этом направлении - что заставляет меня чувствовать себя некомфортно, так это то, что это не будет работать напрямую для чисел с положительным показателем - но я понимаю, что это может сработать для OP . И затем, что-то, что можно сразу поймать [+-], мы уже находимся в области регулярных выражений. (в мои более сварливые дни, когда я был антиреэкспериментатором, я бы не прочь вылечить двоих .replace, просто чтобы избежать и этого)

jsbueno 31.07.2024 01:25

Это не будет работать с положительными показателями.

dawg 31.07.2024 02:13

@dawg легко исправить ..

wim 31.07.2024 03:03

Использование разделения строк или прямой замены может решить эту проблему. Но регулярное выражение с использованием метода re.sub Python также может позаботиться об этом в одной строке, охватывая все крайние случаи (ведущий сигнал и т. д.):

import re
str1='-5.634-5'
num = float(re.sub(r"([0-9\-+.][0-9.]*)([\-+])(\d+)", r"\1e\2\3", str1))
print(num)

читается как: первый символ может быть +-. или цифра, за которой следует последовательность цифр или ., затем сигнал, обозначающий показатель степени, затем несколько цифр показателя степени. Просто добавьте «е» в среднюю группу — и пока мы этим занимаемся, сразу преобразуйте ее в «float», чтобы избавиться от возможного лидирующего «+» :-)

это отлично и полезно для улучшения моей игры с регулярными выражениями, спасибо! Принял другой ответ исключительно из соображений целесообразности этой ситуации.

villaa 31.07.2024 16:37

Я бы сделал что-нибудь в этом духе.

Вы можете одновременно проверить, что число соответствует ожидаемому формату, и зафиксировать составные части с помощью регулярного выражения:

import re 

cases=['-5.634-5','1.234-3','1.234+3','-1.234+3','1+2','-1-2']

for s in cases:
    if m:=re.search(r'^([+-]?\d+(?:\.\d*)?)([+-]\d+)$', s):
        f=float(f'{m.group(1)}e{m.group(2)}')
        print('{0!r:10}\t=>\t{1}'.format(s, f))
    else:
        continue
        # not a good number

Распечатки:

'-5.634-5'  =>  -5.634e-05
'1.234-3'   =>  0.001234
'1.234+3'   =>  1234.0
'-1.234+3'  =>  -1234.0
'1+2'       =>  100.0
'-1-2'      =>  -0.01

Вы можете сопоставить заменяемый пробел с e, указав, что ему не предшествует начало строки, а за ним следует - или +:

import re

str1='-5.634-5'
print(re.sub('(?<!^)(?=[-+])', 'e', str1))

Это выводит:

-5.634e-5

круто, спасибо за эти знания! принял более короткий ответ, но он, вероятно, более элегантен для обобщенного парсера.

villaa 31.07.2024 16:37

Другие вопросы по теме