【问题标题】:How to convert a strictly sorted list of strings into dict?如何将严格排序的字符串列表转换为dict?
【发布时间】:2011-12-10 17:17:37
【问题描述】:

我有一个严格排序的字符串列表:

['a',
 'b',
 'b/c',
 'b/d',
 'e',
 'f',
 'f/g',
 'f/h',
 'f/h/i',
 'f/h/i/j']

此列表类似于树表示。所以,我需要把它转换成dict:

{'a': {},
 'b': {'c': {},
       'd': {}},
 'e': {},
 'f': {'g': {},
       'h': {'i': {'j': {}}}}}

如您所见,此字典中的键是父级,值是子级。

UPD:我同意 empty dict 优于 None

【问题讨论】:

    标签: python string list dictionary tree


    【解决方案1】:

    如果你不坚持None作为叶子值,你可以使用紧凑的代码

    my_dict = lambda: defaultdict(my_dict)
    d = my_dict()
    for x in my_list:
        reduce(defaultdict.__getitem__, x.split("/"), d)
    

    诚然,这段代码的作用并不明显,但它很简洁:)

    【讨论】:

      【解决方案2】:

      这是我的决心:

      from collections import defaultdict
      from pprint import pprint
      
      input = ['a', 'b', 'b/c', 'b/d', 'e', 'f', 'f/g', 'f/h', 'f/h/i', 'f/h/i/j']
      result = defaultdict(dict)
      for i in input:
          path = i.split('/')
          key = path[0]
          value = {}
          buffer = {key:value}
          for folder in path[1:]:
              value[folder] = {}
              value = value[folder]
          result[key].update(buffer[key])
      pprint(dict(result))
      

      【讨论】:

        【解决方案3】:

        这是我的破解之道。我倒转优化路径,因为 pop() 比 pop(0) 快得多。

        def add_branch(root, path):
            branch = path.pop()
            if path:
                if branch not in root or root[branch] is None:
                    root[branch] = {}
                add_branch(root[branch], path)
            else:
                root[branch] = None
        
        def totree(strings):
            root = {}
            for string in strings:
                path = string.split("/")
                path.reverse()
                add_branch(root, path)
            return root
        

        这样使用:

        my_tree = totree(['a', 'b', 'b/c', 'b/d', 'e', 'f', 'f/g', 'f/h', 
            'f/h/i', 'f/h/i/j'])
        

        【讨论】:

          【解决方案4】:

          希望它有所帮助,递归方法:)

          import pprint
          
          l = ['a',
          'b',
          'b/c',
          'b/d',
          'e',
          'f',
          'f/g',
          'f/h',
          'f/h/i',
          'f/h/i/j']
          
          def put(d, elems):
              f = elems[0]
              if len(elems)==1:
                  d[f]=None
              else:
                  if f not in d or d[f]==None:
                      d[f] = {}
                  put(d[f], elems[1:])
          
          d = {}
          for x in l:
              put(d, x.split('/'))
          
          pprint.pprint(d)
          

          【讨论】:

            【解决方案5】:
            di = {}
            for a in arr:
                al = a.split("/")
                d = di
                for elem in al:
                    if elem in d:
                        d = d[elem]
                    else:
                        d[elem]={}
            
            print di
            

            请注意,元素不是按字母顺序存储在字典中的!

            【讨论】:

            • 这不会产生请求的结果,因为它使用{} 而不是None 作为叶值。
            • @lazyr:正确,但我认为 OP 能够根据他的需要调整它:) 它会通过检查它是 None 还是 dict 等来混淆代码,但我认为底层思想比这些实现细节更重要。
            • 此代码对于 ["a", "b/c"] 失败。不过,从规范中并不清楚是否需要涵盖这种情况。
            • @SvenMarnach 此列表["a", "b/c"] 无效。它必须是["a", "b", "b/c"]。也许我应该更清楚地表达我的想法......
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-17
            • 1970-01-01
            • 1970-01-01
            • 2015-05-10
            • 2019-03-27
            相关资源
            最近更新 更多