在Python中从扁平列表创建嵌套字典的通用方法
我想找到一种最简单的通用方法,把这个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”是独一无二的,而且你可以看到这个列表并不一定是按照这个关键字的顺序排列的。
3 个回答
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"])
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
。
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'}]
注意:字典是无序的!但它和你的字典是一样的。