1

我正在研究将多级词典转换为单级词典列表的功能。

逻辑似乎是对的。但是当我运行它时,while 循环会无限运行。我发现它第一次进入 while 循环时next_level.pop()正在工作。从 while 循环的第二次开始,该pop()函数永远不会删除next_level. 我还尝试通过 检索最后一项next_level[-1],并通过 删除最后一项del next_level[-1]。但结果是一样的。我认为这可能与参考事物有关。任何的想法?

def flat_dict(self, params):
    """convert a multi-level dictionary to a list of one-level dictionaries"""
    plist = next_level = []
    next_level.append(params)
    while next_level:
        current_level = temp_level = next_level.pop()
        for k, v in current_level.iteritems():
            if isinstance(v, dict):
                next_level.append(temp_level.pop(k))
                pk = [x for x in next_level[-1].keys() if x.endswith('_id')]
                temp_level[pk[0]] = next_level[-1][pk[0]]
        plist.append(temp_level)
    return plist
4

2 回答 2

1

没有字典的例子,它有点难以形象化......但通常对于这样的情况,我还是建议递归:

def flatten( data ):
    output = []
    if ( isinstance(data, dict) ):
        output.append(data)
        for value in data.values():
            output += flatten(value)
    return output

在直接回答您的问题时,我不能 100% 确定出了什么问题 - 我可以说 pop() 本身就可以正常工作。我猜这与您初始化 plist 的方式有关,您是否遇到了无限循环?

plist = next_level = []

这一行实际上将 plist 和 next_level 设置为相同的确切列表 - 不是为每个变量初始化一个空白列表。

>>> plist = next_level = []
>>> plist.append(1)
>>> next_level
[1]

当您修改 plist 时,稍后在您的循环中,您实际上正在修改 next_level ,这也不是我的预期目的......尝试以这种方式定义您的 plist/next_level :

plist = []
next_level = []

看看会发生什么。

于 2012-08-01T21:06:20.887 回答
0

我不完全理解你想要做什么,所以我认为这个答案不会正是你所需要的。但也许您可以将其用作解决方案的开始。

这个答案不会改变dict要展平的;它只是遍历它并构建一个新dict实例列表。它递归调用自身来展平任意嵌套的dict.

def flat_dict(self, d_to_flatten, lst_flat=None):
    """convert a multi-level dictionary to a list of one-level dictionaries"""
    if lst_flat is None:
        lst_flat = []

    d = {}
    lst = []
    for k, v in d_to_flatten.iteritems():
        if isinstance(v, dict):
            lst.append(v)
        else:
            d[k] = v
    lst_flat.append(d)
    for d in lst:
        flat_dict(self, d, lst_flat)

    return lst_flat
于 2012-08-01T21:21:07.737 回答