您可以使用 setdefault 函数在您浏览数据时自动构建嵌套级别:
data= [
{
"player": "Kevin Durant",
"team": "Thunder",
"location": "Oklahoma City",
"points": 15
},
{
"player": "Jeremy Lin",
"team": "Lakers",
"location": "Los Angeles",
"points": 22
},
{
"player": "Kobe Bryant",
"team": "Lakers",
"location": "Los Angeles",
"points": 51
},
{
"player": "Blake Griffin",
"team": "Clippers",
"location": "Los Angeles",
"points": 26
}
]
nested = dict()
for d in data:
nested.setdefault(d["location"],dict()) \
.setdefault(d["team"], dict()) \
.setdefault(d["player"], list()) \
.append({"points":d["points"]})
输出:
print(nested)
{ 'Oklahoma City':
{
'Thunder':
{ 'Kevin Durant': [{'points': 15}] }
},
'Los Angeles':
{
'Lakers':
{
'Jeremy Lin': [{'points': 22}],
'Kobe Bryant': [{'points': 51}]
},
'Clippers':
{ 'Blake Griffin': [{'points': 26}] }
}
}
[编辑] 概括方法
如果你必须经常在不同类型的字典或层次结构上做这种事情,你可以在一个函数中概括它:
def dictNesting(data,*levels):
result = dict()
for d in data:
r = result
for level in levels[:-1]:
r = r.setdefault(d[level],dict())
r = r.setdefault(d[levels[-1]],list())
r.append({k:v for k,v in d.items() if k not in levels})
return result
然后你会给函数一个字典列表,后面跟着你想要嵌套的键的名称:
byLocation = dictNesting(data,"location","team")
{ 'Oklahoma City':
{ 'Thunder': [
{'player': 'Kevin Durant', 'points': 15}]
},
'Los Angeles':
{'Lakers': [
{'player': 'Jeremy Lin', 'points': 22},
{'player': 'Kobe Bryant', 'points': 51}],
'Clippers': [
{'player': 'Blake Griffin', 'points': 26}]
}
}
如果你想以不同的方式对相同的数据进行分组,你只需要改变字段名称的顺序:
byPlayer = dictNesting(data,"player","location","team")
{ 'Kevin Durant':
{ 'Oklahoma City':
{ 'Thunder': [{'points': 15}] }
},
'Jeremy Lin':
{ 'Los Angeles':
{'Lakers': [{'points': 22}]}
},
'Kobe Bryant':
{ 'Los Angeles':
{'Lakers': [{'points': 51}]}
},
'Blake Griffin':
{ 'Los Angeles':
{'Clippers': [{'points': 26}]}
}
}
您可以从那里获得一些乐趣,并改进它以在最低嵌套级别聚合数据:
def dictNesting(data,*levels,aggregate=False):
result = dict()
for d in data:
r = result
for level in levels[:-1]:
r = r.setdefault(d[level],dict())
r = r.setdefault(d[levels[-1]],[list,dict][aggregate]())
content = ( (k,v) for k,v in d.items() if k not in levels)
if aggregate:
for k,v in content: r.setdefault(k,list()).append(v)
else:
r.append(dict(content))
return result
输出:
byCity = dictNesting(data,"location","team",aggregate=True)
{ 'Oklahoma City':
{'Thunder':
{'player': ['Kevin Durant'], 'points': [15]}},
'Los Angeles':
{'Lakers':
{'player': ['Jeremy Lin', 'Kobe Bryant'], 'points': [22, 51]},
'Clippers':
{'player': ['Blake Griffin'], 'points': [26]}
}
}
lakersPlayers = byCity["Los Angeles"]["Lakers"]["player"]
# ['Jeremy Lin', 'Kobe Bryant']
lakersPoints = sum(byCity["Los Angeles"]["Lakers"]["points"])
# 73