【问题标题】:String containing list and other data types to dictionary without changing the data type in python包含列表和其他数据类型的字符串到字典而不更改python中的数据类型
【发布时间】:2019-01-15 15:08:33
【问题描述】:

我有一个字符串如下:

key_val = "count=2, name=['hello', 'hi'], word='Dial::100', roll=12"

我需要从下面的字符串中获取字典:

d_key_val = {'count'=2, 'name'=['hello', 'hi'], 'word'='Dial::100', 'roll'=12}

我尝试了以下方法:

regx = r'(?P<key>\w+)=(?P<value>\[.+?\]|\d+|\S+)'
r_key_val = re_findall(regx, key_val)
for key, value in r_key_val:
        d_key_val[key] = value

但它将值存储为所有字符串:

d_key_val = {'count'='2', 'name'="['hello', 'hi']", 'word'="'Dial::100'", 'roll'='12'}

是否有任何方法或正则表达式将值存储为与字符串中相同的数据类型?

【问题讨论】:

标签: python


【解决方案1】:

如果你100%确定数据是“安全的”,你可以eval它作为dict的参数:

>>> key_val = "count=2, name=['hello', 'hi'], word='Dial::100', roll=12"
>>> eval("dict(%s)" % key_val)
{'count': 2, 'name': ['hello', 'hi'], 'roll': 12, 'word': 'Dial::100'}

如果您不确定,最好不要使用eval


或者,您可以使用您的正则表达式并使用ast.literal_eval 来评估value

>>> regx = r'(?P<key>\w+)=(?P<value>\[.+?\]|\d+|\S+)'
>>> {k: ast.literal_eval(v) for k, v in re.findall(regx, key_val)}
{'count': 2, 'name': ['hello', 'hi'], 'roll': 12, 'word': ('Dial::100',)}

(注意:我没有详细检查您的正则表达式。)您可以也尝试将ast.literal_eval 应用于整个表达式,而不是不太安全的eval,但这需要一些预处理,例如用: 替换= 并在键中添加引号,这可能不适用于例如包含这些符号的字符串值。

【讨论】:

    【解决方案2】:

    regex 不能这样做,但你可以!您可以编写如下函数,将values regex 写出并将它们转换为适当的类型。

    def type_converter(v):
        if v[0] == '[' and v[-1] == ']':
            v = v.replace('[', '').replace(']', '')
            return [type_converter(x) for x in v.split(',')]
        try:
            v = int(v)
        except ValueError:
            try:
                v = float(v)
            except ValueError:
                pass
        finally:
            return v
    

    要将其添加到您的代码中,只需执行以下操作:

    regx = r'(?P<key>\w+)=(?P<value>\[.+?\]|\d+|\S+)'
    r_key_val = re_findall(regx, key_val)
    for key, value in r_key_val:
        d_key_val[key] = type_converter(value)  # <- this
    

    例子:

    lst = ['2', '1.2' ,'foo', '[1, 2]']
    print([type(type_converter(x)) for x in lst ])  
    # [<class 'int'>, <class 'float'>, <class 'str'>, <class 'list'>]
    

    请注意,try 块的写入顺序非常重要,因为 float('1') 不会引发任何错误,但正确的类型是 int

    【讨论】:

    • 不过,list 部分更难。也许改用ast.literal_eval
    • @tobias_k 我后来注意到了,但我将函数更新为递归函数来处理它。归根结底,ast.literal_eval 或一些花哨的json 命令可能会更方便。
    猜你喜欢
    • 2013-09-28
    • 2022-08-15
    • 2019-05-28
    • 1970-01-01
    • 2014-01-10
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多