2016-09-21 27 views
-2

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

{ 
    "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 
+1

那么你有什么到目前为止自己写的吗? –

+1

请编辑您的问题以添加详细信息,请勿将其置于评论中。 –

回答

0
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 
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'}] 
+0

感谢您的想法。有效。我能够根据这里包含的信息更新我的代码。 – MikeG

0

你缺少在下一节一个条件检查你的原始解决方案:

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 v2,该else块永远不会被执行,你因此总是得到空的列表。

+0

我曾尝试过。它不起作用,因为“部分路径”被破坏了。这是问题所在。来自@Maurice的解决方案照顾到了这一点。 – MikeG