使用Python将深层嵌套字典转换为1D字典

问题描述:

我有一些深度随机嵌套字典,如下所示。使用Python将深层嵌套字典转换为1D字典

 
{'CompilationStatistics': {'CodeGeneration': {'EndTime': '2010-04-21T14:03:11', 
               'StartTime': '2010-04-21T14:03:11', 
               'StepList': {'EliminatingDuplicates': {'EndTime': '2010-04-21T14:03:11', 
                        'NumberOfFilesEliminated': '14', 
                        'StartTime': '2010-04-21T14:03:11'}, 
                  'ModuleGenerator': {'EndTime': '2010-04-21T14:03:11', 
                       'StartTime': '2010-04-21T14:03:11'}, 
                  'Munger': {'EndTime': '2010-04-21T14:03:11', 
... 

我该如何将它转换成1D字典如下。

 
dict["CompilationStatistics_CodeGeneration_EndTime"] = '2010-04-21T14:03:11' 
dict["CompilationStatistics_CodeGeneration_StartTime"] = '2010-04-21T14:03:11' 
... 
dict["CompilationStatistics_directory] = "/abc" 

简单的是做递归:

import collections 

def flattendict(d, prefix=()): 
    r = {} 
    for k, v in d.iteritems(): 
    pk = prefix + (k,) 
    if isinstance(v, collections.Mapping): 
     r.update(flattendict(v, pk)) 
    else: 
     r['_'.join(pk)] = v 
    return r 

下面是一个例子使用:

d = {'foo': 'bar', 
    'baz': {'fie': 'foo', 'zip': 'zap'}, 
    'bam': {'fie': 'foo', 'zip': {'zap': 'zup', 'mep': 'mop'}}, 
    } 
print flattendict(d) 

p (可能,当然,按不同顺序)

{'baz_zip': 'zap', 'bam_fie': 'foo', 'foo': 'bar', 'bam_zip_mep': 'mop', 
'baz_fie': 'foo', 'bam_zip_zap': 'zup'} 

哼哼,有趣......

这是一个递归函数的绝佳机会。这里有一个,据我的初步测试,将做的工作:

def convert(dct_in, dct_out=None, prefix='', sep='_'): 
    if dct_out is None: 
     dct_out = {} 
    if prefix: 
     prefix += sep 
    for k, v in dct_in.iteritems(): 
     k_str = prefix + k 
     if isinstance(v, dict): 
      convert(v, dct_out, k_str, sep) 
     else: 
      dct_out[k_str] = v 
    return dct_out 

递归:

def flatten_dict(d): 
    subdicts = (([(k+"_"+k2, v2) for k2,v2 in flatten_dict(v).iteritems()] 
       if isinstance(v, dict) 
       else [(k,v)]) 
       for k,v in d.iteritems()) 
    return dict((k,v) for sd in subdicts for k,v in sd)