繁体   English   中英

如何从以字符串表示的数字中检索Python格式的代码?

[英]How to retrieve Python format code from number represented as string?

我将数字数据存储在ASCII txt文件中,即不同参数的值,每个参数都有一列。 列之间的格式可能有所不同,但在列内不会更改。 我将该数据加载到Python中,进行处理并将其写回到ASCII文件中。 关键是: 数字的格式不应更改。 表示小数位应仍然相同,exp表示法仍应为exp表示法,依此类推。 因此,我需要一个函数,该函数返回表示一个数字的每个字符串的格式代码(然后我可以在处理过程中将其与数字一起存储)。 注意:参数类型在处理期间不会改变; 即整数将保持整数,浮点数将保持浮点数等(否则,保持格式代码没有多大意义)。

我的想法是使用正则表达式分析字符串,以确定它是否是int,float,float以指数表示法等:

import re
string = '3.142'
# positive match then detected as
match = re.fullmatch(r'[+|-]*[0-9]+[.][0-9]*', string.strip())

按照此一般分类,我将解析字符串以确定例如小数位。 例如

string = '3.142' # I know from above that it is a float and not exp notation...
lst = string.strip().split('.')
if not lst[1]: # trailing zeros are hidden
    result = '{:+g}' if '+' in lst[0] else '{:g}'
else:
    result = '{0:+.' if '+' in lst[0] else '{0:.'
    result += str(len(lst[1])) + 'f}'

print(result) # gives... '{0:.3f}'

问:这似乎很笨拙; -有人有更好的解决方案吗?

在思考了一段时间后,我对自己的问题的回答:由于缺乏信息,这是一种不可能的倒置。

例。 假设您读取了字符串“ -5.5”。 如果数字的精度为1位或尾随的零被隐藏,则您已经缺乏信息。 另一个(非数字)问题是您不知道它是否为“有符号”值,即,如果它为正数,则是否为“ +5.5”。 想要更多? 以“ 1.2E + 1”为例。 这可能是整数12。尽管不太可能,但您不确定。

除此之外,Python方面还有一些小限制,例如据我所知, {:E}.format()将始终生成带符号的,零填充的2位数指数(当然,如果<100 ),即像'... E + 01',尽管您可能想要'... E + 1'。 关于数字格式的另一件事是隐藏的前导零和尾随零,请参见此处的问题。 普通的字符串格式设置选项似乎似乎不包括删除前导/后缀零–您需要其他帮助程序,例如.lstrip(“0”)

我的想法是,在返回格式代码从字符串到数字再到字符串的过程中,至少做得不错。 使用一点regex进行一般分类,然后使用简单的.split()等。

import re
class NumStr():
    def analyse_format(self, s, dec_sep='.'):
        """
        INPUT: 
            s, string, representing a number
        INPUT, optional: 
            dec_sep, string, decimal separator
        WHAT IT DOES:
            1) analyse the string to achieve a general classification
                (decimal, no decimal, exp notation)
            2) pass the string and the general class to an appropriate
                parsing function.
        RETURNS: 
            the result of the parsing function:
                tuple with
                    format code to be used in '{}.format()'
                    suited Python type for the number, int or float.
        """
        # 1. format definitions. key = general classification.
        redct = {'dec': '[+-]?[0-9]+['+dec_sep+'][0-9]*|[+-]?[0-9]*['+dec_sep+'][0-9]+',
                 'no_dec': '[+-]?[0-9]+',
                 'exp_dec': '[+-]?[0-9]+['+dec_sep+'][0-9]*[eE][+-]*[0-9]+',
                 'exp_no_dec': '[+-]?[0-9]+[eE][+-]*[0-9]+'}
        # 2. analyse the format to find the general classification.
        gen_class, s = [], s.strip()
        for k, v in redct.items():
            test = re.fullmatch(v, s)
            if test:
                gen_class.append(k)
        if not gen_class:
            raise TypeError("unknown format -->", s)
        elif len(gen_class) > 1:
            raise TypeError("ambiguous result -->", s, gen_class)
        # 3. based on the general classification, call string parsing function
        method_name = 'parse_' + str(gen_class[0])
        method = getattr(self, method_name, lambda *args: "Undefined Format!")
        return method(s, *dec_sep)

    def parse_dec(self, s, dec_sep):
        lst = s.split(dec_sep)
        result = '{:f}' if len(lst[1]) == 0 else '{:.'+str(len(lst[1]))+'f}'
        result = result.replace(':', ':+') if '+' in lst[0] else result
        return (result, float)

    def parse_no_dec(self, s, *dec_sep):
        result = '{:+d}' if '+' in s else '{:d}'
        return (result, int)

    def parse_exp_dec(self, s, dec_sep):
        lst_dec = s.split(dec_sep)
        lst_E = lst_dec[1].upper().split('E')
        result = '{:.'+str(len(lst_E[0]))+'E}'
        result = result.replace(':', ':+') if '+' in lst_dec[0] else result
        return (result, float)

    def parse_exp_no_dec(self, s, *dec_sep):
        lst_E = s.upper().split('E')
        result = '{:+E}' if '+' in lst_E[0] else '{:E}'
        return (result, float)

并进行测试:

valid = ['45', '45.', '3E5', '4E+5', '3E-3', '2.345E+7', '-7',
         '-45.3', '-3.4E3', ' 12 ', '8.8E1', '+5.3', '+4.',
         '+10', '+2.3E121', '+4e-3','-204E-9668','.7','+.7']
invalid = ['tesT', 'Test45', '7,7E2', '204-100', '.']

如果您有任何改进的想法,我很乐意将它们包括在内! 我想人们已经遇到了这个问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM