如何在Python中通过分隔符拆分键来创建嵌套字典?
我有一个字典,长得像这样:
a = {
'customer_name': 'bob',
'customer_phone': '555-1212',
'order_0_number': 'A33432-24',
'order_0_date': '12/12/12',
'order_1_number': 'asd24222',
'order_1_date': '12/14/12'
}
我需要把它按下划线分开,然后放进一个嵌套的字典里,像这样:
b = {
'customer': {
'name': 'bob',
'phone': '555-1212'
},
'order': {
'0': {
'date': '12/12/12',
'number': '...' },
'1': { ... etc.
其实我手上的数据比这个要复杂得多。
我现在做到这一步,但在用Python实现的时候卡住了:
def expand_data(field, value):
split_field = field.split('_', 1)
#base case, end of string
if len(split_field) == 1:
child_element[split_field[0] = value
return child_element
else:
child_element[split_field[0]] = expand_data(split_field[1],value)
return child_element
b = {}
for k,v in a.iteritems():
b += expand_data(k, v) # stuck here because I can't add nested dicts together
不过我不太确定这是不是正确的做法。我还没运行过这段代码,现在只是想想而已。
另外,字典的键将来可能会变,所以我只能依靠下划线来进行分割。而且我也不知道需要嵌套多深。
4 个回答
0
这里有一个通用的解决方案,并附带了一些注释:
def expand_flatdict_to_tree(dict, sep = '_', to_lower = True):
tree = {}
for src, val in dict.items():
ref = tree
if to_lower:
src = src.lower()
for i, part in enumerate(src.split(sep)):
if part not in ref:
ref[part] = {}
if i == len(src.split(sep)) -1:
ref[part] = val # we cannot do ref = val after loop, as assignment to the ref itself will be passed by assignment
break
ref = ref[part] # update nest reference
return tree
flat_dict = {
'LOGLEVEL': 'INFO',
'DB_ENABLED': True,
'DB_CONNECTOR_HOST': 'localhost',
'DB_CONNECTOR_USER': 'root',
}
print (expand_flatdict_to_tree(flat_dict))
# {
# 'loglevel': 'INFO',
# 'db': {
# 'enabled': True,
# 'connector': {
# 'host': 'localhost',
# 'user': 'root'
# }
# }
# }
0
这里有一些步骤可以参考,但我不会给出代码,因为你没有展示你的代码。
- 首先,遍历你的键,可以用
for key in yourDico
这个方式很简单。 - 接着,找出你的模式,比如
customer
和order
,这样可以把值分开,得到你想要的内容。 - 根据第一次分开的结果,创建一个新的字典,如果里面还有
_
这个符号(看起来是你用来分割的字符),就继续分割。
0
b = {}
b["customer"] = {"name": a["customer_name"], "phone": a["customer_phone"]}
for key in a.keys():
if key.startswith("order_"):
o, i, f = key.split("_")
order = b.get("order", {})
order_i = order.get(i, {})
order_i[f] = a[key]
b["order"] = order
b["order"][i] = order_i
print(b)
输出结果:
{'customer': {'name': 'bob', 'phone': '555-1212'},
'order': {'0': {'date': '12/12/12', 'number': 'A33432-24'},
'1': {'date': '12/14/12', 'number': 'asd24222'}}}
3
一个通用的解决方案:
def nest_dict(flat_dict, sep='_'):
"""Return nested dict by splitting the keys on a delimiter.
>>> from pprint import pprint
>>> pprint(nest_dict({'title': 'foo', 'author_name': 'stretch',
... 'author_zipcode': '06901'}))
{'author': {'name': 'stretch', 'zipcode': '06901'}, 'title': 'foo'}
"""
tree = {}
for key, val in flat_dict.items():
t = tree
prev = None
for part in key.split(sep):
if prev is not None:
t = t.setdefault(prev, {})
prev = part
else:
t.setdefault(prev, val)
return tree
if __name__ == '__main__':
import doctest
doctest.testmod()