将深度嵌套的字典转换为一维字典

40 阅读2分钟

有时候,我们可能会遇到一些深度嵌套的字典,需要将其转换为一维字典。例如,以下是一个深度嵌套的字典:

{'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',
...

我们需要将其转换为以下一维字典:

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

2、解决方案

我们可以使用递归的方法来完成这个任务。这里提供三种不同的递归方法:

方法一:

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

方法二:

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)

以上三种方法都可以将深度嵌套的字典转换为一维字典。我们可以根据自己的需要选择其中一种方法来使用。

代码例子:

d = {'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',
...

# 使用方法一
print(flattendict(d))

# 使用方法二
print(convert(d))

# 使用方法三
print(flatten_dict(d))

以上代码将输出如下结果:

{'CompilationStatistics_CodeGeneration_EndTime': '2010-04-21T14:03:11', 'CompilationStatistics_CodeGeneration_StartTime': '2010-04-21T14:03:11', ...}
{'CompilationStatistics_CodeGeneration_EndTime': '2010-04-21T14:03:11', 'CompilationStatistics_CodeGeneration_StartTime': '2010-04-21T14:03:11', ...}
{'CompilationStatistics_CodeGeneration_EndTime': '2010-04-21T14:03:11', 'CompilationStatistics_CodeGeneration_StartTime': '2010-04-21T14:03:11', ...}