变量名和值字符串到字典

2024-10-01 09:20:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含变量名和值的字符串。名称和值之间没有指定的分隔符,名称可能包含下划线,也可能不包含下划线。你知道吗

string1 = 'Height_A_B132width_top100.0lengthsimple0.00001'

我想把变量放到字典里:

# desired output: dict1 = {'Height_A_B': 132, 'width_top': 100.0, 'lengthsimple': 0.00001}

尝试以下itertools方法

输入1:

from itertools import groupby
[''.join(g) for _, g in groupby(string1, str.isdigit)]

输出1:

['Height_A_B', '132', 'width_top', '100', '.', '0', 'lengthsimple', '0', '.', '00001']

下面应该差不多到了,但是iPython解释器告诉我str属性不存在(它在文档中)。不管怎样。。。你知道吗

输入2:

[''.join(g) for _, g in groupby(string1, str.isnumeric)]

输出2:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-25-cf931a137f50> in <module>()
----> 1 [''.join(g) for _, g in groupby(string1, str.isnumeric)]

AttributeError: type object 'str' has no attribute 'isnumeric'

不管怎样,如果这个数字包含一个带“+”或“-”符号的指数,会发生什么?你知道吗

string2 = 'Height_A132width_top100.0lengthsimple1.34e+003'
# desired output: dict2 = {'Height_A_B': 132, 'width_top': 100.0, 'lengthsimple': 1.34e+003}

输入3:

[''.join(g) for _, g in groupby(string2, str.isdigit)]

输出3:

['Height_A', '132', 'width_top', '100', '.', '0', 'lengthsimple', '1', '.', '34', 'e+', '003']

我想知道,如果有人有一个优雅的解决方案?你知道吗

更新: 下面有一些关于保留数值变量类型的讨论(例如int、float等)。事实上,string2中的科学表示法有点像是一条红鲱鱼,因为如果你创建一个变量

>>> a = 1.34e+003

你得到了吗

>>> print a
1340.0

不管怎样,产生一个1.34+003的字符串的几率很低。你知道吗

所以string2是一个更合适的测试用例,如果我们把它改成

string2 = 'Height_A132width_top100.0lengthsimple1.34e+99'

Tags: 字符串in名称fortopwidthjoinheight
3条回答

给你:

import re
p = re.compile(ur'([a-zA-z]+)([0-9.]+)')
test_str = u"Height_A_B132width_top100.0lengthsimple0.00001"

print dict(re.findall(p, test_str))

用科学记数法处理数字使这变得有点棘手,但用一个精心编写的正则表达式是可能的。希望我的正则表达式在所有数据上都能正确运行。:)

import re

def parse_numstr(s):
    ''' Convert a numeric string to a number. 
    Return an integer if the string is a valid representation of an integer,
    Otherwise return a float, if its's a valid rep of a float,
    Otherwise, return the original string '''
    try:
        return int(s)
    except ValueError:

        try:
            return float(s)
        except ValueError:
            return s

pat = re.compile(r'([A-Z_]+)([-+]?[0-9.]+(?:e[-+]?[0-9]+)?)', re.I)

def extract(s):
    return dict((k, parse_numstr(v)) for k,v in pat.findall(s))

data = [
    'Height_A_B132width_top100.0lengthsimple0.00001',
    'Height_A132width_top100lengthsimple1.34e+003',
    'test_c4.2E1p-3q+5z123E-2e2.71828',
]

for s in data:
    print(extract(s))

输出

{'Height_A_B': 132, 'width_top': 100.0, 'lengthsimple': 1.0000000000000001e-05}
{'width_top': 100, 'Height_A': 132, 'lengthsimple': 1340.0}
{'q': 5, 'p': -3, 'z': 1.23, 'test_c': 42.0, 'e': 2.71828}

请注意,我的正则表达式将接受科学记数法中包含多个小数点的格式错误的数字,parse_numstr将作为字符串返回。如果您的数据不包含这种格式错误的数字,这应该不是问题。你知道吗

这里有一个稍微好一点的正则表达式。它只允许一个小数点,但也会接受格式错误的数字,小数点两边都没有数字,如..E1

pat = re.compile(r'([A-Z_]+)([-+]?[0-9]*\.?[0-9]*(?:e[-+]?[0-9]+)?)', re.I)

另请参见this answer,以获取用科学记数法表示数字的正则表达式。你知道吗

您可以使用regex:([^\d.]+)(\d[\d.e+-]*)

  1. [^\d.]意思是:除了数字和句点以外的一切
  2. +表示一个或多个。你知道吗
  3. 其他组至少需要一个数字,然后是数字或e或-/+。你知道吗

组1是键,组2是值。你知道吗

demo

代码:

import re
vals = { x:float(y) if '.' in y else int(y) for (x,y) in (re.findall(r'([^\d.]+)(\d[\d.e+-]*)',string2))} 

{'width_top': 100.0, 'Height_A': 132, 'lengthsimple': 1340.0}

相关问题 更多 >