将点分隔的字符串解析为字典变量

时间:2015-06-17 01:41:43

标签: python string dictionary

我有字符串值,

"a"
"a.b"
"b.c.d"

如何将它们转换为python字典变量,

a
a["b"]
b["c"]["d"]

字符串的第一部分(在点之前)将成为字典名称,其余的子字符串将成为字典键

4 个答案:

答案 0 :(得分:3)

eval在这里相当危险,因为这是不受信任的输入。您可以使用正则表达式获取字典名称和密钥名称,并使用varsdict.get进行查找。

import re

a = {'b': {'c': True}}

in_ = 'a.b.c'
match = re.match(
    r"""(?P<dict>      # begin named group 'dict'
          [^.]+        #   one or more non-period characters
        )              # end named group 'dict'
        \.             # a literal dot
        (?P<keys>      # begin named group 'keys'
          .*           #   the rest of the string!
        )              # end named group 'keys'""",
    in_,
    flags=re.X)

d = vars()[match.group('dict')]
for key in match.group('keys'):
    d = d.get(key, None)
    if d is None:
        # handle the case where the dict doesn't have that (sub)key!
        print("Uh oh!")
        break
result = d

# result == True

甚至更简单:分裂点。

in_ = 'a.b.c'
input_split = in_.split('.')
d_name, keys = input_split[0], input_split[1:]

d = vars()[d_name]
for key in keys:
    d = d.get(key, None)
    if d is None:
        # same as above
result = d

答案 1 :(得分:2)

s = "a.b.c"
s = s.replace(".", "][")+"]" # 'a][b][c]'
i = s.find("]") # find the first "]"
s = s[:i]+s[i+1:] # remove it 'a[b][c]'
s = s.replace("]", "\"]").replace("[", "[\"") # add quotations 'a["b"]["c"]'
# you can now execute it:
v = eval(s)

答案 2 :(得分:1)

我遇到了同样的问题,在不同的部分解析带有点分隔键的ini文件。 e.g:

[app]
site1.ftp.host = hostname
site1.ftp.username = username
site1.database.hostname = db_host
; etc..

所以我写了一个小函数来将“add_branch”添加到现有的dict树中:

def add_branch(tree, vector, value):
    """
    Given a dict, a vector, and a value, insert the value into the dict
    at the tree leaf specified by the vector.  Recursive!

    Params:
        data (dict): The data structure to insert the vector into.
        vector (list): A list of values representing the path to the leaf node.
        value (object): The object to be inserted at the leaf

    Example 1:
    tree = {'a': 'apple'}
    vector = ['b', 'c', 'd']
    value = 'dog'

    tree = add_branch(tree, vector, value)

    Returns:
        tree = { 'a': 'apple', 'b': { 'c': {'d': 'dog'}}}

    Example 2:
    vector2 = ['b', 'c', 'e']
    value2 = 'egg'

    tree = add_branch(tree, vector2, value2)    

    Returns:
        tree = { 'a': 'apple', 'b': { 'c': {'d': 'dog', 'e': 'egg'}}}

    Returns:
        dict: The dict with the value placed at the path specified.

    Algorithm:
        If we're at the leaf, add it as key/value to the tree
        Else: If the subtree doesn't exist, create it.
              Recurse with the subtree and the left shifted vector.
        Return the tree.

    """
    key = vector[0]
    tree[key] = value \
        if len(vector) == 1 \
        else add_branch(tree[key] if key in tree else {},
                        vector[1:],
                        value)
    return tree

答案 3 :(得分:0)

pyjq库的功能与此非常相似,不同之处在于您必须显式提供一个字典作为根,并且必须在字符串前面加上一个.来引用任何字典。你的根。

python:

import pyjq
d = { 'a' : { 'b' : { 'c' : 'd' } } }
for path in ['.a', '.a.b', '.b.c.d', '.x']:
    print(pyjq.first(path, d))

输出:

{'b': {'c': 'd'}}
{'c': 'd'}
None
None