在Python上的一组字典上递归循环

时间:2016-12-20 14:23:17

标签: python dictionary recursion

我正在尝试将一组包含后续值的字典循环到一起来制作一个大字典。 基本上有一个字典,其中有列表(包含字典),这些列表分布在包含字典列表的不同字典中。

这可能很令人困惑,所以下面你会找到我做的词典的一个例子:

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。大家节日快乐! :)

1 个答案:

答案 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意味着你永远不应该在不受控制的输入上使用它