2016-03-03 5 views
2

У меня есть список словарей, в которых мало кто может быть вложен. Я хочу сделать его плоским списком словарей.
Здесь Message - это список словарей с ключом «Message_content».
Я хотел бы вывести «Message_content» в случае, если он содержит ключевое сообщение.

Вложение может быть любым уровнем. Я имею в виду «MESSAGE_CONTENT» может снова содержать «Message», хотя пример, показанный здесь, на одном уровне

вводаПреобразование списка вложенных словарей в плоский список словарей

Message = [ 
    {'Message_content': {'Argument': [{'Arg_name': 'acl_name'}, {'Arg_name': 'acl_type'}], 
         'Message': {'Message_content': {'Argument': [{'Arg_name': 'cat_name'}, {'Arg_name': 'cat_enum'}]}}}}, 
    {'Message_content': {'Argument': [{'Arg_name': 'ac_name'}, {'Arg_name': 'ac_type'}]}} 
     ] 

Ожидаемый результат:

Message = [ 
    {'Message_content': {'Argument': [{'Arg_name': 'acl_name'}, {'Arg_name': 'acl_type'}]}}, 
    {'Message_content': {'Argument': [{'Arg_name': 'cat_name'}, {'Arg_name': 'cat_enum'}]}}, 
    {'Message_content': {'Argument': [{'Arg_name': 'ac_name'}, {'Arg_name': 'ac_type'}]}} 
    ] 

Пробовал писать рекурсивную функцию, но не может обрабатывать гнездование.
Любая помощь будет оценена по достоинству.

ответ

2

Рекурсия здесь довольно проста. Вы можете решить ее следующим образом:

input = [ 
    {'Message_content': { 
      'Argument': [{ 'Arg_name': 'acl_name' }, { 'Arg_name': 'acl_type' }], 
      'Message': { 'Message_content': { 'Argument': [{ 'Arg_name': 'cat_name' }, { 'Arg_name': 'cat_enum' }] } } 
    }}, 
    { 'Message_content': { 'Argument': [{ 'Arg_name': 'ac_name' }, { 'Arg_name': 'ac_type' }] } } 
] 

def handle_element(elem, output): 
    try: 
     arg = elem["Message_content"]["Argument"] 
     output.append(arg) 
    except KeyError: 
     pass 
    try: 
     msg = elem["Message_content"]["Message"] 
     print "nested" 
     handle_element(msg, output) 
    except KeyError: 
     print "not nested" 


out = [] 
for elem in input: 
    handle_element(elem, out) 

print out 

В качестве альтернативы, чтобы избежать переполнения стека из-за рекурсивных вызовов, вы можете превратить его в итеративный процесс, используя список для отслеживания элементов, которые будут обрабатываться. Способ вставки вложенных элементов в список будет определять порядок вложенных элементов, отображаемых в выходном списке. Здесь вы обрабатываете вложенные структуры в конце «очереди»:

message = [ 
    {'Message_content': { 
      'Argument': [{ 'Arg_name': 'acl_name' }, { 'Arg_name': 'acl_type' }], 
      'Message': { 'Message_content': { 'Argument': [{ 'Arg_name': 'cat_name' }, { 'Arg_name': 'cat_enum' }] } } 
    }}, 
    { 'Message_content': { 'Argument': [{ 'Arg_name': 'ac_name' }, { 'Arg_name': 'ac_type' }] } } 
] 

elements_to_handle = message 
def handle_element(elem, output): 
    try: 
     arg = elem["Message_content"]["Argument"] 
     output.append(arg) 
    except KeyError: 
     pass 
    try: 
     msg = elem["Message_content"]["Message"] 
     elements_to_handle.append(msg) 
    except KeyError: 
     pass 


out = [] 
while len(elements_to_handle): 
    handle_element(elements_to_handle.pop(), out) 

print out 
Смежные вопросы