【问题标题】:Recursive looping on a set of dictionaries on PythonPython上一组字典的递归循环
【发布时间】:2016-12-20 14:23:16
【问题描述】:

我正在尝试循环一组包含彼此后续值的字典以创建一个大字典。 基本上有一个字典,其中有列表(包含字典),这些列表分布在包含字典列表的不同字典中。

这可能很混乱,所以下面是我制作的词典示例:

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-listdata-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'}}} 

所以,我的问题是:“为什么会这样?” 可能不用说,但我的目标(当然)是获取所有的键和值。 我一遍又一遍地检查我的代码,就是想不通......

任何帮助将不胜感激!

附:祝大家节日快乐! :)

【问题讨论】:

  • 我很困惑。你到底想做什么?那些对eval 的调用是一个危险信号
  • 是的,我认为它可能是...... :D 我会进行编辑并尝试更清楚。但基本上我想循环第一个字典(datapage1)并将其他字典中的值添加到指定位置。有一个“sub_dir/location”信息指向另一个具有更多值的字典。这个 sub_dir/location -dict 可以继续到另一个包含更多值的 dict。所有这些值都应附加到 datapage1-dict 的适当位置。因此递归循环遍历 datapage1 并附加这些 sub_dir 的...
  • P.S.我使用eval 只是因为我不知道有任何其他方法可以将[sub_dir][location]-value 用作字典位置...

标签: python dictionary recursion


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

【讨论】:

  • **这完美!非常感谢@SergeBallesta! ** ...但我还是有点困惑。那么是对原始字典的修改导致了不一致吗?另外,感谢eval 的提醒。我注意到 eval 不是首选的使用方法,但是还有其他方法可以将值作为 dict 键传递吗?上周末我一直在寻找解决方案,但这是唯一有效的解决方案?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-09
  • 1970-01-01
相关资源
最近更新 更多