【问题标题】:Extracting all path from a multi-level dictionary从多级字典中提取所有路径
【发布时间】:2015-11-09 09:57:38
【问题描述】:

我有一本这样的字典:

dirDict = {"DIR1" : {
                    "DIR11" : { 
                                "DIR111" : "Maki111",
                                "DIR112" : "Maki112"
                                }, 
                    "DIR12" : "Maki12", 
                    "DIR13" : {
                                "DIR131" : "Maki131"
                                }
                }
    }

把它想象成一个文件夹结构。我想得到与os.walk 类似的文件夹结构。像这样的:

["DIR1/DIR11/DIR111/Maki111",
"DIR1/DIR11/DIR112/Maki112",
"DIR1/DIR12/Maki12",
"DIR1/DIR13/DIR131/Maki131"]

所以它基本上是字典值的所有路径。我用递归函数尝试了很多方法,但我迷路了。

这是我最近的试用:

def walk(input_dict, path_string = "",  result = ""):
    for key, value in input_dict.items():
        if isinstance(value, dict):
            path_string += "/" + key
            print "==== DICT ====", "\nkey: ", key, "\nvalue: ", value, "\n\t\tpath_string: ", path_string
            result = walk(value, path_string)
            print "\t\t\t\tresulting: ", result
        elif isinstance(value, str):
            print "==== NOT DICT ===="
            path_string += "/" + value
            print "\t\tpath_string: ", path_string, "\nvalue: ", value
            return path_string
        else:
            path_string = "/" + key
        result += "\n" + result
    return result

【问题讨论】:

  • “我试过” - 请输入代码

标签: python dictionary multi-level


【解决方案1】:

使用 Python 3:

dirDict = {"DIR1" : {
                    "DIR11" : {
                                "DIR111" : "Maki111",
                                "DIR112" : "Maki112"
                                },
                    "DIR12" : "Maki12",
                    "DIR13" : {
                                "DIR131" : "Maki131"
                                }
                }
    }

def recurse(d, prefix=None, sep='/'):
    if prefix is None:
        prefix = []
    for key, value in d.items():
        if isinstance(value, dict):
            yield from recurse(value, prefix + [key])
        else:
            yield sep.join(prefix + [key, value])

print(list(recurse(dirDict)))

输出:

['DIR1/DIR13/DIR131/Maki131', 'DIR1/DIR11/DIR111/Maki111', 'DIR1/DIR11/DIR112/Maki112', 'DIR1/DIR12/Maki12']

【讨论】:

    【解决方案2】:
    def walk(d, path):
        paths = []
        if len(d) == 0:
            return path
        for k, v in d.iteritems():
            child_path = path + k + '/'
            if isinstance(v, basestring):
                paths.append(child_path + v)
            else:
                paths.extend(walk(v, child_path))
        return paths
    

    【讨论】:

    • 是否可以像我提议的那样返回一个列表?
    • 谢谢。只有一条评论。如果值为空字典,它会跳过键,例如:“DIR16”:{}
    • @Prag 我添加了这个案例
    【解决方案3】:

    我在https://gist.github.com/nvie/f304caf3b4f1ca4c3884#gistcomment-1597937 发布的walk 函数可以用来帮助解决您的问题:

    def walk(obj, parent_first=True):
    
        # Top down?
        if parent_first:
            yield (), obj
    
        # For nested objects, the key is the path component.
        if isinstance(obj, dict):
            children = obj.items()
    
        # For nested lists, the position is the path component.
        elif isinstance(obj, (list, tuple)):
            children = enumerate(obj)
    
        # Scalar values have no children.
        else:
            children = []
    
        # Recurse into children
        for key, value in children:
            for child_path, child in walk(value, parent_first):
                yield (key,) + child_path, child
    
        # Bottom up?
        if not parent_first:
            yield (), obj
    

    您的问题可以通过以下方式解决:

    for path, value in walk(obj):
        if isinstance(value, str):  # leaf node
            path_with_value = path + (value,)
            print("/".join(path_with_value))
    

    【讨论】:

      【解决方案4】:

      具有列表理解的紧凑解决方案:

      def f(v):
          if isinstance(v, dict):
              return dict_to_list(v)
          elif isinstance(v, list):
              return v
          else:
              return [v]
      
      def dict_to_list(d):
          return ['{}/{}'.format(k, i) for k, v in d.items() for i in f(v)]
      
      lst = dict_to_list(dirDict)
      lst.sort()
      print('\n'.join(lst))
      

      【讨论】:

        猜你喜欢
        • 2017-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-18
        • 1970-01-01
        • 1970-01-01
        • 2015-04-14
        相关资源
        最近更新 更多