【问题标题】:Converting python dictionary to unique key-value pairs将python字典转换为唯一的键值对
【发布时间】:2017-01-29 09:08:21
【问题描述】:

我想将 python 字典转换为包含所有可能的键值对的列表。例如,如果 dict 是这样的:

{
    "x": {
            "a1": { "b": {
                            "c1": { "d": { "e1": {}, "e2": {} } },
                            "c2": { "d": { "e3": {}, "e4": {} } }
                        }
                },
            "a2": { "b": {
                            "c3": { "d": { "e1": {}, "e5": {} } },
                            "c4": { "d": { "e6": {} } }
                        }
                 }
       }
}

我想要一个类似的列表:

[
  { "x": "a1", "b": "c1", "d": "e1" },
  { "x": "a1", "b": "c1", "d": "e2" },
  { "x": "a1", "b": "c2", "d": "e3" },
  { "x": "a1", "b": "c2", "d": "e4" },
  { "x": "a2", "b": "c3", "d": "e1" },
  { "x": "a2", "b": "c3", "d": "e5" },
  { "x": "a2", "b": "c4", "d": "e6" }
]

我正在努力编写递归函数。 我已经写了这个,但它不起作用

def get_list(groups, partial_row):
    row = []
    for k, v in groups.items():
        if isinstance(v, dict):
            for k2, v2 in v.items():
                partial_row.update({k: k2})
                if isinstance(v2, dict):
                    row.extend(get_list(v2, partial_row))
                else:
                    row.append(partial_row)

    return row

【问题讨论】:

  • 那么你自己到目前为止写了什么?
  • edit您的问题添加详细信息,请勿在评论中添加。

标签: python list dictionary flatten


【解决方案1】:

替代解决方案:

from pprint import pprint
dic = {
    "x": {
            "a1": { "b": {
                            "c1": { "d": { "e1": {}, "e2": {} } },
                            "c2": { "d": { "e3": {}, "e4": {} } }
                        }
                },
            "a2": { "b": {
                            "c3": { "d": { "e1": {}, "e5": {} } },
                            "c4": { "d": { "e6": {} } }
                        }
                 }
       }
}


def rec(dic, path=[], all_results=[]):
    if not dic:
        # No items in the dictionary left, add the path
        # up to this point to all_results

        # This is based on the assumption that there is an even
        # number of items in the path, otherwise you output format
        # makes no sense
        even_items = path[::2]
        odd_items = path[1::2]
        result = dict(zip(even_items, odd_items))
        all_results.append(result)
        return all_results

    for key in dic:
        # Make a copy of the current path
        path_cp = list(path)
        path_cp.append(key)
        all_results = rec(dic[key], path_cp, all_results)

    return all_results


results = rec(dic)

pprint(results)

输出:

[{'b': 'c2', 'd': 'e4', 'x': 'a1'},
 {'b': 'c2', 'd': 'e3', 'x': 'a1'},
 {'b': 'c1', 'd': 'e1', 'x': 'a1'},
 {'b': 'c1', 'd': 'e2', 'x': 'a1'},
 {'b': 'c3', 'd': 'e5', 'x': 'a2'},
 {'b': 'c3', 'd': 'e1', 'x': 'a2'},
 {'b': 'c4', 'd': 'e6', 'x': 'a2'}]

【讨论】:

  • 感谢您的想法。有效。我能够根据此处包含的信息更新我的代码。
【解决方案2】:
a = {
"x": {
    "a1": { "b": {
                    "c1": { "d": { "e1": {}, "e2": {} } },
                    "c2": { "d": { "e3": {}, "e4": {} } }
                }
        },
    "a2": { "b": {
                    "c3": { "d": { "e1": {}, "e5": {} } },
                    "c4": { "d": { "e6": {} } }
                }
         }
}
}


def print_dict(d, depth, *arg):
    if type(d) == dict and len(d):
        for key in d:
            if not len(arg):
                new_arg = key
            else:
                new_arg = arg[0] + (': ' if depth % 2 else ', ') + key
            print_dict(d[key], depth+1, new_arg)
    else:
        print(arg[0])

print_dict(a, depth=0)

结果:

x: a1, b: c1, d: e1
x: a1, b: c1, d: e2
x: a1, b: c2, d: e4
x: a1, b: c2, d: e3
x: a2, b: c4, d: e6
x: a2, b: c3, d: e1
x: a2, b: c3, d: e5

【讨论】:

    【解决方案3】:

    您在原始解决方案的以下部分中缺少一项条件检查:

    if isinstance(v2, dict):
        row.extend(get_list(v2, partial_row))
    else:
        row.append(partial_row)
    

    应该是这样的

    if isinstance(v2, dict) and v2:
        row.extend(get_list(v2, partial_row))
    else:
        row.append(partial_row)
    

    由于缺少and v2else 块永远不会被执行,因此您总是得到空列表。

    【讨论】:

    • 我以前试过。它不起作用,因为“部分路径”被破坏了。这就是问题所在。 @Maurice 的解决方案解决了这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 2015-07-17
    • 2021-10-09
    相关资源
    最近更新 更多