Reputation: 207
I have a list of dictionaries in which few may be nested.
I want to make it a flat list of dictionaries.
Here, Message is a list of dictionaries that has a key 'Message_content'.
I would like to pop out 'Message_content' in case if it contains a key Message.
The nesting could be to any level. I mean 'Message_content' might again contain 'Message' though the example shown here is for one level
Input
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'}]}}
]
Expected output:
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'}]}}
]
Tried writing a recursive function but unable to handle the nesting.
Any help would be appreciated.
Upvotes: 2
Views: 602
Reputation: 292
The recursion here is quite simple. You can tackle it like so:
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
Alternatively, to avoid stack overflow due to recursive calls, you can transform it into an iterative process, using a list to track the elements to be handled. The way you insert the nested elements into the list will decide on the order of the nested things appearing in the output list. Here, you handle the nested structures at the end of the "queue":
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
Upvotes: 2