【问题标题】:parse a dot seperated string into dictionary variable将点分隔的字符串解析为字典变量
【发布时间】:2015-09-02 01:29:30
【问题描述】:

我有字符串值,

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

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

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

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

【问题讨论】:

  • 如何输出字典?
  • 没有得到问题。你真正想要发生什么?你可以说得更详细点吗?您是否希望a 成为键为b 的字典,然后b 成为键为c 的字典,其中字典作为值,键为d
  • yes tomasyany...字符串的第一部分(点之前)将成为字典名称,其余子字符串将成为字典键...
  • 那么a会是存储字典的变量吗?

标签: python string dictionary


【解决方案1】:

pyjq 库的作用与此非常相似,除了您必须明确提供一个字典作为根目录,并且您必须在字符串前面加上 . 前缀以引用您的根目录。

蟒蛇:

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

【讨论】:

    【解决方案2】:

    我在解析具有不同部分的点分隔键的 ini 文件时遇到了同样的问题。例如:

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

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

    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
    

    【讨论】:

    • 超级有帮助。我将其用作人们使用的交叉点,并使用带有此模式标记的列的 Excel 工作表,以便我可以进行批量 api 调用,尽管我需要在逻辑中添加一些以使其工作:rowObj.update(add_branch (rowObj,colName.split("."),rowValue))
    【解决方案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
    

    【讨论】:

      【解决方案4】:
      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)
      

      【讨论】:

      • 计算结果为 a[b][c]a["b"]["c"]。为了解决这个问题,我在eval 之前添加了两行,分别是s = s.replace("]", "\"]")s = s.replace("[", "[\"")
      • 哦,那我应该修好了
      猜你喜欢
      • 2016-04-17
      • 2012-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-15
      相关资源
      最近更新 更多