我有这样的字典:
{"key1:key2[0]:key3[0]": "1234",
"key1:key2[0]:key4[0]:key5": "4567",
"key1:key2[1]:key3[0]": "789",
"key1:key2[1]:key4[1]:key5": "12345"}
键是表示目标字典中每个最终值的谱系的描述性方式。 :
将父键与其子键分开,[]
表示以前键的值是列表,并且大括号之间存在索引。
鉴于此,我如何构建像
这样的字典{
"key1":{
"key2":[
{
"key3":["1234"],
"key4":[{"key5":"4567"}]
},
{
"key3":["789"],
"key4":[{"key5":"12345"}]
}
]
}
}
我试图做这样的事情:
result_dict = {}
def populate(target_path, value):
current_point_in_path = None
t = result_dict
target_path = target_path.split(":")
for i, each_key in enumerate(target_path):
list_index = re.findall(r'\[(.*?)\]', each_key)
if len(list_index) > 1:
raise Exception("not allowed")
elif len(list_index) == 1:
index = int(list_index[0])
key_before = each_key.split(index)[0]
if not isinstance(result_dict[key_before], list):
t = t.setdefault(key_before, [])
if i+1 == len(target_path):
# the issue is that this insert won't return a pointer to the current index element like setdefault would do
# alternate soultions are wc
t.insert(index, value)
else:
t.insert(index, {})
else:
if i + 1 == len(target_path):
t = t.setdefault(each_key, value)
else:
t = t.setdefault(each_key, {})
我无法在这里完成部分代码。也许我需要一个更好的设计与我的描述性语言。欢迎任何建议。
答案 0 :(得分:1)
您可以将itertools.groupby
与递归一起使用:
import re, itertools
d = {"key1:key2[0]:key3": "1234", "key1:key2[0]:key4": "4567", "key1:key2[1]:key3": "789", "key1:key2[1]:key4": "12345"}
new_d = [(re.findall('\w+', a), b) for a, b in d.items()]
def last_group(d):
return [{a[-1]:c for a, c in list(b)} for _, b in itertools.groupby(sorted(d, key=lambda x:x[0][1]), key=lambda x:x[0][1])]
def group_data(d):
return {a:(lambda x:group_data([(c[1:], d) for c, d in x]) if all(len(c) > 3 for c, _ in x) else last_group(x))(list(b)) for a, b in itertools.groupby(sorted(d, key=lambda x:x[0][0]), key=lambda x:x[0][0])}
print(group_data(new_d))
输出:
{'key1': {'key2': [{'key3': '1234', 'key4': '4567'}, {'key3': '789', 'key4': '12345'}]}}
答案 1 :(得分:1)
你可以使用这个怪物:
def populate(result_dict, target_path, value):
# split path
target_path = re.findall(r"[^:]+?(?=\[|:|$)|\[\d+?\]", target_path)
# prepare path
for i, element in enumerate(target_path):
if element[0] == "[" and element[-1] == "]":
element = int(element[1:-1])
target_path[i] = element
current = result_dict
for i, element in enumerate(target_path[:-1]):
if isinstance(element, str): # dict index
if element not in current: # create new entry
if isinstance(target_path[i + 1], str): # next is a dict
current[element] = {}
else: # next is a list
current[element] = []
elif isinstance(element, int): # list index
if element >= len(current): # create new entry
current.extend(None for _ in range(element-len(current)+1))
if current[element] is None:
if isinstance(target_path[i + 1], str): # next is a dict
current[element] = {}
else: # next is a list
current[element] = []
current = current[element]
if isinstance(target_path[-1], int):
current.append(value)
else:
current[target_path[-1]] = value
您可以使用此代码填写字典:
result_dict = {}
for key, value in {"key1:key2[0]:key3[0]": "1234",
"key1:key2[0]:key4[0]:key5": "4567",
"key1:key2[1]:key3[0]": "789",
"key1:key2[1]:key4[1]:key5": "12345"}.items():
populate(result_dict, key, value)
print(json.dumps(result_dict, indent=4))
打印:
{
"key1": {
"key2": [
{
"key3": [
"1234"
],
"key4": [
{
"key5": "4567"
}
]
},
{
"key3": [
"789"
],
"key4": [
null,
{
"key5": "12345"
}
]
}
]
}
}