【问题标题】:Generic way to create nested dictionary from flat list in python从python中的平面列表创建嵌套字典的通用方法
【发布时间】:2012-01-03 11:44:21
【问题描述】:

我正在寻找最简单的通用方法来转换这个python列表:

x = [
        {"foo":"A", "bar":"R", "baz":"X"},
        {"foo":"A", "bar":"R", "baz":"Y"},
        {"foo":"B", "bar":"S", "baz":"X"},
        {"foo":"A", "bar":"S", "baz":"Y"},
        {"foo":"C", "bar":"R", "baz":"Y"},
    ]

进入:

foos = [ 
         {"foo":"A", "bars":[
                               {"bar":"R", "bazs":[ {"baz":"X"},{"baz":"Y"} ] },
                               {"bar":"S", "bazs":[ {"baz":"Y"} ] },
                            ]
         },
         {"foo":"B", "bars":[
                               {"bar":"S", "bazs":[ {"baz":"X"} ] },
                            ]
         },
         {"foo":"C", "bars":[
                               {"bar":"R", "bazs":[ {"baz":"Y"} ] },
                            ]
         },
      ]

"foo","bar","baz" 的组合是唯一的,正如您所见,列表不一定按此键排序。

【问题讨论】:

  • 你的(不一定是最简单的,但你自己的)方法是什么?

标签: python dictionary


【解决方案1】:
#!/usr/bin/env python3
from itertools import groupby
from pprint import pprint

x = [
        {"foo":"A", "bar":"R", "baz":"X"},
        {"foo":"A", "bar":"R", "baz":"Y"},
        {"foo":"B", "bar":"S", "baz":"X"},
        {"foo":"A", "bar":"S", "baz":"Y"},
        {"foo":"C", "bar":"R", "baz":"Y"},
    ]


def fun(x, l):
    ks = ['foo', 'bar', 'baz']
    kn = ks[l]
    kk = lambda i:i[kn]
    for k,g in groupby(sorted(x, key=kk), key=kk):
        kg = [dict((k,v) for k,v in i.items() if k!=kn) for i in g]
        d = {}
        d[kn] = k
        if l<len(ks)-1:
            d[ks[l+1]+'s'] = list(fun(kg, l+1))
        yield d

pprint(list(fun(x, 0)))

[{'bars': [{'bar': 'R', 'bazs': [{'baz': 'X'}, {'baz': 'Y'}]},
           {'bar': 'S', 'bazs': [{'baz': 'Y'}]}],
  'foo': 'A'},
 {'bars': [{'bar': 'S', 'bazs': [{'baz': 'X'}]}], 'foo': 'B'},
 {'bars': [{'bar': 'R', 'bazs': [{'baz': 'Y'}]}], 'foo': 'C'}]

注意: dict 是无序的!但它和你的一样。

【讨论】:

    【解决方案2】:

    我将定义一个执行单个分组步骤的函数,如下所示:

    from itertools import groupby
    def group(items, key, subs_name):
        return [{
            key: g,
            subs_name: [dict((k, v) for k, v in s.iteritems() if k != key)
                for s in sub]
        } for g, sub in groupby(sorted(items, key=lambda item: item[key]),
            lambda item: item[key])]
    

    然后做

    [{'foo': g['foo'], 'bars': group(g['bars'], "bar", "bazs")} for g in group(x,
         "foo", "bars")]
    

    这会为foos 提供所需的结果。

    【讨论】:

      【解决方案3】:

      这是一个简单的数据循环,没有递归。值是字典键的辅助树在构建时用作结果树的索引。

      def make_tree(diclist, keylist):
          indexroot = {}
          root = {}
          for d in diclist:
              walk = indexroot
              parent = root
              for k in keylist:
                  walk = walk.setdefault(d[k], {})
                  node = walk.setdefault('node', {})
                  if not node:
                      node[k] = d[k]
                      parent.setdefault(k+'s',[]).append(node)
                  walk = walk.setdefault('children', {})
                  parent = node
          return root[keylist[0]+'s']
      
      foos = make_tree(x, ["foo","bar","baz"])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-01
        相关资源
        最近更新 更多