2012-01-03 69 views
7

我找转换这条巨蟒列表的最简单的通用方式:通用方式,从平面列表的嵌套词典在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"} ] }, 
          ] 
     }, 
     ] 

结合“富“,”bar“,”baz“是唯一的,正如你所看到的,列表不一定是由这个键来命令的。

+6

什么是你的(不一定是最简单的,但你的)这样做的方式? – eumiro 2012-01-03 11:47:55

回答

3
#!/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'}] 

注:字典是无序的!但是和你的一样。

0

我将定义执行一个单一的分组步骤这样的功能:

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期望的结果。

0

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

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"])