Create a nested list from list of dictionaries

Viewed 84

I have following list of dictionaries

[ 
{"Control":"[check11] Enable MFA", "Message":"account x1"},
{"Control":"[check11] Enable MFA", "Message":"account x2"},
{"Control":"[check12] Rotate keys", "Message":"account x1"},
{"Control":"[check12] Rotate keys", "Message":"account x2"}
]

I'd like to get unique values for "Control" and all of the control "Message", so it would look something like this

[
["[check11] Enable MFA", "account x1", "account x2"],
["[check12] Rotate keys", "account x1", "account x2"]
]

If someone has any idea on how to make it work, I'd really appreciate the hint.

3 Answers

You can try itertools.groupby

from itertools import groupby

l = [ 
{"Control":"[check11] Enable MFA", "Message":"account x1"},
{"Control":"[check11] Enable MFA", "Message":"account x2"},
{"Control":"[check12] Rotate keys", "Message":"account x1"},
{"Control":"[check12] Rotate keys", "Message":"account x2"}
]

l.sort(key = lambda x: x["Control"]) # this sorting is required
# beacuse if the sequence is (0,0,1,1,0,2,2)
# groupby will group like ((0,0), (1,1), (0), (2,2))

output = []
for grp_name, group in groupby(l, key= lambda x: x["Control"]):
    output.append([grp_name, *[g['Message'] for g in group]])
    
print(output)
[['[check11] Enable MFA', 'account x1', 'account x2'], 
['[check12] Rotate keys', 'account x1', 'account x2']]

Using itertools.groupby you can achieve that

from itertools import groupby
from operator import itemgetter

values = [
    {"Control": "[check11] Enable MFA", "Message": "account x1"},
    {"Control": "[check11] Enable MFA", "Message": "account x2"},
    {"Control": "[check12] Rotate keys", "Message": "account x1"},
    {"Control": "[check12] Rotate keys", "Message": "account x2"}
]

key = itemgetter("Control")

result = [[key, *[i['Message'] for i in val]]
          for key, val in groupby(sorted(values, key=key), key=key)]

Or with a collections.defaultdict

from collections import defaultdict
result = defaultdict(list)
for row in values:
    result[row["Control"]].append(row['Message'])
result = [[key, *val] for key, val in result.items()]

You can do it with Pandas (l is your list):

import pandas as pd
df=pd.DataFrame(l)
gr=df.groupby('Control')['Message'].apply(list)
res=[[i]+gr[i] for i in gr.index]

print(res)

Output:

[['[check11] Enable MFA', 'account x1', 'account x2'], ['[check12] Rotate keys', 'account x1', 'account x2']]
Related