在python中展平嵌套结构

时间:2014-06-04 19:03:40

标签: python nested structure

我如何在Python中将其展平,以便每个"小部件"是列表的元素吗?

{  "widgets" :[{"num": "1", "letter": "a",
              "widgets" :[{"num": "2", "letter": "b",
                           "widgets" :[{"num": "3","letter": "c"},
                                       {"num": "4", "letter": "d"}]
                         }]
            }]
}

所以它最终成为

[{"num":"1", "letter","a"},
 {"num": "2", "letter":"b"},
 {"num": "3", "letter":"c"},
 {"num": "4", "letter":"d"}] 

3 个答案:

答案 0 :(得分:4)

在你拍摄那些给你这些数据的人后,可能是这样的:

def flatten_widgets(widget):
    stack = [widget['widgets']]
    while stack:
        for widget in stack.pop():
            yield {k: v for k, v in widget.items() if k != 'widgets'}
            if 'widgets' in widget:
                stack.append(widget['widgets'])

>>> list(flatten_widgets(a))

[{'letter': 'a', 'num': '1'},
 {'letter': 'b', 'num': '2'},
 {'letter': 'c', 'num': '3'},
 {'letter': 'd', 'num': '4'}]

答案 1 :(得分:1)

这是一个递归的solution

def flatten_widget(widget):
    assert isinstance(widget, dict)

    # Remove any sub-level widgets for processing
    widgets = widget.pop('widgets', None)

    # The first object is itself, unless it contains nothing
    flat_list = [widget] if widget else []

    # If there are sub-level widgets, flatten them
    if widgets:
        assert isinstance(widgets, list)
        # Recursively flatten each widget and add it return list
        for w in widgets:
            flat_list += flatten_widget(w)

    # Return all widgets in a list
    return flat_list

print flatten_widget(widget)
# [{'num': '1', 'letter': 'a'}, {'num': '2', 'letter': 'b'}, {'num': '3', 'letter': 'c'}, {'num': '4', 'letter': 'd'}]

请注意,它不会检测循环引用。此外,它假设您不介意修改原始数据结构。我没有对它进行基准测试,但我猜不必复制每个dict项目会更快一些。

答案 2 :(得分:0)

这是我草率的反应;在写完之后,我意识到它没有按照你指定的顺序列出项目;但是我认为这可能会指出你在递归方面的正确方向,就像其他答案一样。

注意:没有导入python模块"优雅"。 ;)

def getflattenedwidgetlist(thislist):
    thislevellist = list()
    for dictionary in thislist:
        thisdict = dict()
        thislevellist.append(thisdict)
        for key in dictionary:
            if key != "widgets":
                thisdict[key] = dictionary[key]

        if "widgets" in dictionary:
            return getflattenedwidgetlist(dictionary["widgets"]) + [thisdict]

    return thislevellist


stuff = {
   "widgets" :[{
       "num": "1",
       "letter": "a",
       "widgets" :[{
         "num": "2",
         "letter": "b",
         "widgets" :[{
             "num": "3",
             "letter": "c"
           },
           { 
            "num": "4",
            "letter": "d"
           }]
        }]
    }] 
}

print getflattenedwidgetlist([stuff])