Laxmikant
Laxmikant

Reputation: 2216

concatenate dictionaries over a key

I have a list of dictionaries (with some data fetched from an API) assume:

alist = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'c':35}, {'a':1, 'b':2, 'c':87}..]

There are multiple dictionaries which are repeated in alist. But only one of key has a different values out of repeated dictionaries.So, the query is:

What's the easiest way to combine those dictionaries by keeping separate values in a list?

like:

alist = [{'a':1, 'b':2, 'c':[3, 35, 87]}...]

Update - I have a list which specifies me the repeated keys like:

repeated_keys = ['c',...] 

Upvotes: 1

Views: 92

Answers (4)

Learner
Learner

Reputation: 5292

Use defaultdict (it is faster ) and generate dictionary from it- you can also easily convert that dictionary into list.You can modify j in i.keys() to filter keys.

from  collections import defaultdict as df

d=df(list)

alist = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'c':35}, {'a':1, 'b':2, 'c':87}]

for i in alist:
    for j in i.keys():
        d[j].append(i[j])

print dict(d.items())

Output-

{'a': [1, 1, 1], 'c': [3, 35, 87], 'b': [2, 2, 2]}

If you want to get rid of repeated element from that use dict-comprehension and set-

>>>{k:list(set(v)) for k,v in d.items()}
>>>{'a': [1], 'c': [35, 3, 87], 'b': [2]}

Upvotes: 2

Kenly
Kenly

Reputation: 26688

It is possible to get your result.You have to test if you want to create a list if items has different values or keep it as is.

repeated_keys is used to store repeated keys and count how many times they are repeated.

alist = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'c':35}, {'a':1, 'b':2, 'c':87}]

z = {}
repeated_keys = {}
for dict in alist:
    for key in dict:
        if z.has_key(key):
            if isinstance(z[key], list):
                if not dict[key] in z[key]:
                    repeated_keys[key] +=1
                    z[key].append(dict[key])
            else:
                if z[key] != dict[key]:
                    repeated_keys[key] = 1
                    z[key] = [z[key], dict[key]]

        else:
            z[key] = dict[key]

print 'dict: ',z
print 'Repeated keys: ', repeated_keys

output:

dict:  {'a': [1, 3], 'c': [3, 35, 87], 'b': 2}
Repeated keys:  {'c'}

if:

alist = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'c':35}, {'a':1, 'b':2, 'c':87}, {'a':3,'b':2}]

output should be:

dict:  {'a': [1, 3], 'c': [3, 35, 87], 'b': 2}
Repeated keys:  {'a': 1, 'c': 2}

Upvotes: 1

Martijn Pieters
Martijn Pieters

Reputation: 1121406

You could use a list comprehension:

result = [alist[0].copy()]
result[0]['c'] = [d['c'] for d in alist]

Note that there is little point in making this a list again; you combined everything into one dictionary, after all:

result = dict(alist[0], c=[d['c'] for d in alist])

If you have multiple repeated keys, you have two options:

  • Loop and get each key out:

    result = alist[0].copy()
    for key in repeated:
        result[key] = [d[key] for d in alist]
    
  • Make all keys lists, that way you don't have to keep consulting your list of repeated keys:

    result = {}
    for key in alist[0]:
        result[key] = [d[key] for d in alist]
    

The latter option is alternatively implemented by iterating over alist just once:

result = {}
for d in alist:
    for key, value in d.items():
        result.setdefault(key, []).append(value)

Upvotes: 1

Tom Ron
Tom Ron

Reputation: 6181

from collections import defaultdict
con_dict = defaultdict(list)
alist = [{'a':1, 'b':2, 'c':3}, {'a':1, 'b':2, 'c':35}, {'a':1, 'b':2, 'c':87}]

for curr_dict in alist:
    for k, v in curr_dict.iteritems():
        con_dict[k].append(v)

con_dict = dict(con_dict)

We create a default dict of type list and then iterate over the items and append them in the right key.

Upvotes: 1

Related Questions