我正在尝试将一组包含后续值的字典循环到一起来制作一个大字典。 基本上有一个字典,其中有列表(包含字典),这些列表分布在包含字典列表的不同字典中。
这可能很令人困惑,所以下面你会找到我做的词典的一个例子:
datapage1 = {"events":{"data":[{"A":{"1_2": "2",
"1_3":{"data":[{"a_ORIGINAL":"1"},
{"a_ORIGINAL":"2"},
{"a_ORIGINAL":"3"}],
"sub_dir":{"location":"datapage11b"}},
"1_4":"4",
"1_5":"5",
"1_6":"6",}},
{"B":"2_1"},
{"C":"3_1"},
{"D":"4_1"},
{"E":"5_1"}],
"sub_dir":{"location":"datapage2"}} }
datapage2 = {"data":[{"F" : "FROMdata2"},
{"G":"FROMdata2"},
{"H":"FROMdata2"},
{"I":"FROMdata2"},
{"J":"FROMdata2"}],
"sub_dir":{"location": "datapage3"}}
datapage3 = {"data":[{"K":"FROMdata3"},
{"L":"FROMdata3"},
{"M":{"FROMdata3": "1",
"13_2":{"data":[{"data3_ORIGINAL":"1"},
{"data3_ORIGINAL":"2"},
{"data3_ORIGINAL":"3"}],
"sub_dir":{"location":"datapage33b"}},
"13_3":"3",
"13_4":"4",
"13_5":"5",}},
{"N":"FROMdata3"},
{"O":"FROMdata3"}],
"sub_dir":{"nolocation": "None"}}
datapage11b = {"data":[{"FROMdata11b SUB_ADDED":"4"},
{"FROMdata11b SUB_ADDED":"5"},
{"FROMdata11b SUB_ADDED":"6"}],
"sub_dir":{"location":"datapage11c"}}
datapage11c = {"data":[{"FROMdata11c SUB_ADDED":"7"},
{"FROMdata11c SUB_ADDED":"8"},
{"FROMdata11c SUB_ADDED":"9"}],
"sub_dir":{"location":"datapage33b"}}
datapage33b = {"data":[{"FROMdata33b SUB_ADDED":"4"},
{"FROMdata33b SUB_ADDED":"5"},
{"FROMdata33b SUB_ADDED":"6"}],
"sub_dir":{"location":"datapage44c"}}
datapage44c = {"data":[{"FROMdata44c SUB_ADDED":"1"},
{"FROMdata44c SUB_ADDED":"2"},
{"FROMdata44c SUB_ADDED":"3"}],
"sub_dir":{"nolocation":"None"}}
基本上每个字典都有一个 data -key,其中包含一个列表。此数据列表在 data -key中的另一个字典中继续。
如果要继续列表, sub_dir -key指向正确的字典。
我通过查看本网站上的其他解决方案编译了一个递归循环,它有点有用,但并不完全。 这是我的循环:
def findSubDict(v, prefix=''):
if isinstance(v, dict):
for k, v2 in v.items():
if k == 'location':
borrow_dir = v2
upOne = prefix.replace("sub_dir", "data")
for item in eval(borrow_dir + "['data']"):
eval("datapage1" + upOne + ".append(item)")
while "location" in eval(borrow_dir + "['sub_dir']"):
borrow_dir = eval(borrow_dir + "['sub_dir']['location']")
for item in eval(borrow_dir + "['data']"):
eval("datapage1" + upOne + ".append(item)")
p2 = "{}['{}']".format(prefix, k)
findSubDict(v2, p2)
elif isinstance(v, list):
for i, v2 in enumerate(v):
p2 = "{}[{}]".format(prefix, i)
findSubDict(v2, p2)
findSubDict(datapage1)
pprint.pprint(datapage1)
当我尝试运行它时,结果不一致。例如,我得到了以下几个结果,但是当我多次尝试时,我注意到events['data'][12]['13_2']['data']
中的某些键和值有时会丢失。
(我用“----->”突出显示输出中缺少的键和值)
{'events': {'data': [{'A': {'1_2': '2',
'1_3': {'data': [{'a_ORIGINAL': '1'},
{'a_ORIGINAL': '2'},
{'a_ORIGINAL': '3'},
{'FROMdata11b SUB_ADDED': '4'},
{'FROMdata11b SUB_ADDED': '5'},
{'FROMdata11b SUB_ADDED': '6'},
{'FROMdata11c SUB_ADDED': '7'},
{'FROMdata11c SUB_ADDED': '8'},
{'FROMdata11c SUB_ADDED': '9'},
{'FROMdata33b SUB_ADDED': '4'},
{'FROMdata33b SUB_ADDED': '5'},
{'FROMdata33b SUB_ADDED': '6'},
{'FROMdata44c SUB_ADDED': '1'},
{'FROMdata44c SUB_ADDED': '2'},
{'FROMdata44c SUB_ADDED': '3'}],
'sub_dir': {'location': 'datapage11b'}},
'1_4': '4',
'1_5': '5',
'1_6': '6'}},
{'B': '2_1'},
{'C': '3_1'},
{'D': '4_1'},
{'E': '5_1'},
{'F': 'FROMdata2'},
{'G': 'FROMdata2'},
{'H': 'FROMdata2'},
{'I': 'FROMdata2'},
{'J': 'FROMdata2'},
{'K': 'FROMdata3'},
{'L': 'FROMdata3'},
{'M': {'13_2': {'data': [{'data3_ORIGINAL': '1'},
{'data3_ORIGINAL': '2'},
{'data3_ORIGINAL': '3'},
-----> {'FROMdata33b SUB_ADDED': '4'},
-----> {'FROMdata33b SUB_ADDED': '5'},
-----> {'FROMdata33b SUB_ADDED': '6'},
-----> {'FROMdata44c SUB_ADDED': '1'},
-----> {'FROMdata44c SUB_ADDED': '2'},
-----> {'FROMdata44c SUB_ADDED': '3'}],
'sub_dir': {'location': 'datapage33b'}},
'13_3': '3',
'13_4': '4',
'13_5': '5',
'FROMdata3': '1'}},
{'N': 'FROMdata3'},
{'O': 'FROMdata3'}],
'sub_dir': {'location': 'datapage2'}}}
所以,我的问题是:“为什么会这样?” 可能不用提了,但我的目标(当然)是获得所有的关键和价值观。 我一遍又一遍地检查我的代码,只是想不出来......
任何帮助将不胜感激!
P.S。大家节日快乐! :)
答案 0 :(得分:1)
我做了一些测试,在其中一个测试中,我发现自己修改了原来的字典......并且在不一致的情况下像你一样摔倒,因为相同的字典可能会被多次使用,例如datapage33b和datapage44c。
因此,我决定使用以下代码处理副本并获得一致的结果,这些代码一旦处理完就没有保留sub_dir
部分:
def process(dic):
cr = None
if not isinstance(dic, dict):
return dic
if 'data' in dic:
cr = {'data': [ process(d) for d in dic['data'] ] }
else:
cr = { k: process(dic[k]) for k in dic }
try:
temp = process(eval(dic['sub_dir']['location']))['data']
cr['data'].extend(temp)
except KeyError:
pass
return cr
但是要小心:就像你的原始代码一样,这个代码使用eval
意味着你永远不应该在不受控制的输入上使用它