Python concatenates dictionary keys and values ​​using comprehension

HOW TO CONSULT the following with python COMPREHENSION

FROM (list of dicts)

[
 {'server':'serv1','os':'Linux','archive':'/my/folder1'}
 ,{'server':'serv2','os':'Linux','archive':'/my/folder1'}
 ,{'server':'serv3','os':'Linux','archive':'/my/folder2'}
 ,{'server':'serv4','os':'AIX','archive':'/my/folder1'}
 ,{'server':'serv5','os':'AIX','archive':'/my/folder1'}
]

      

TO (a list of dicts with a tuple as a key and a list of "server # as value

[
 {('Linux','/my/folder1'):['serv1','serv2']}
 ,('Linux','/my/folder2'):['serv3']}
 .{('AIX','/my/folder1'):['serv4','serv5']}
]

      

+3


source to share


2 answers


having to be able to set default values ​​for your dictionary and have the same key multiple times can lead to some inconvenience. i would prefer something like this:

a defaultdict

might help:

from collections import defaultdict

lst = [
 {'server':'serv1','os':'Linux','archive':'/my/folder1'},
 {'server':'serv2','os':'Linux','archive':'/my/folder1'},
 {'server':'serv3','os':'Linux','archive':'/my/folder2'},
 {'server':'serv4','os':'AIX','archive':'/my/folder1'},
 {'server':'serv5','os':'AIX','archive':'/my/folder1'}
]

dct = defaultdict(list)

for d in lst:
    key = d['os'], d['archive']
    dct[key].append(d['server'])

      

If you prefer to have a standard dictionary at the end (in fact, I really don't see a good enough reason for this), you can use dict.setdefault

to create an empty list where the key doesn't exist yet:



dct = {}

for d in lst:
    key = d['os'], d['archive']
    dct.setdefault(key, []).append(d['server'])

      

documentation on defaultdict

(vs. setdefault

)
:

This method is simpler and faster than the equivalent technique using dict.setdefault ()

+4


source


Difficult to achieve with list comprehension due to the accumulation effect. However, it can be used itertools.groupby

in a list sorted by your keys (use the same function key

for sorting and grouping).

Then, extract the server information in concept and list prefix using a group key. Pass the resulting (group key, server list) into the dictionary comprehension and here you go.

import itertools

lst = [
 {'server':'serv1','os':'Linux','archive':'/my/folder1'}
 ,{'server':'serv2','os':'Linux','archive':'/my/folder1'}
 ,{'server':'serv3','os':'Linux','archive':'/my/folder2'}
 ,{'server':'serv4','os':'AIX','archive':'/my/folder1'}
 ,{'server':'serv5','os':'AIX','archive':'/my/folder1'}
]


sortfunc = lambda x : (x['os'],x['archive'])

result = {k:[x['server'] for x in v] for k,v in itertools.groupby(sorted(lst,key=sortfunc),key = sortfunc)}


print(result)

      



I get:

{('Linux', '/my/folder1'): ['serv1', 'serv2'], ('AIX', '/my/folder1'): ['serv4', 'serv5'], ('Linux', '/my/folder2'): ['serv3']}

      

Keep in mind that this is not because it can be written on one line, but that it is more efficient. The approach defaultdict

doesn't require sorting, for example.

+1


source







All Articles