2012-01-03 76 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"])