Преобразование глубоко вложенного словаря в одномерный словарь с помощью Python - PullRequest
0 голосов
/ 11 июля 2010

У меня есть несколько глубоко случайно вложенных словарей, как показано ниже.

{'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"

Ответы [ 3 ]

2 голосов
/ 11 июля 2010

Самое простое сделать это рекурсивно:

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)

производство (возможно, конечно, в другом порядке)

{'baz_zip': 'zap', 'bam_fie': 'foo', 'foo': 'bar', 'bam_zip_mep': 'mop',
 'baz_fie': 'foo', 'bam_zip_zap': 'zup'}
1 голос
/ 11 июля 2010

Рекурсивный:

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)
1 голос
/ 11 июля 2010

Хммм, интересно ...

Это прекрасная возможность для рекурсивной функции.Вот тот, который, согласно моим предварительным тестам, сделает эту работу:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...