Reputation: 152
Updated in an attempt to be more clear
I have three list of dictionaries that I want to merge into one based on a value.
The lists looks like this. They vary in how many dictionaries that they can have.
unplanned = [{'service__name': u'Email', 'service_sum': 4}, {'service__name': u'Peoplesoft', 'service_sum': 2}]
planned = [{'service__name': u'Email', 'service_sum': 2}, {'service__name': u'Gopher', 'service_sum': 2}, {'service__name': u'Peoplesoft', 'service_sum': 4}]
emerg = [{'service__name': u'Internet', 'service_sum': 1}]
I want to take the 3 lists and and create a new list that has the name's from all 3 lists and the values or 0 in a set order. So I am thinking something like this.
[(Email, (4, 2, 0)), (Peoplesoft, (2, 4, 0)), Gopher, (0, 2, 0)), Internet, (0, 0, 1))]
I thought I should create a list of the service__name's to compare against each list so I did that but I am not sure how to compare the 3 lists against this name list. I thought izip_longest would work but have no idea how to implement it. I am using 2.7.
Upvotes: 1
Views: 1824
Reputation: 1030
Try the following codes. You can give variables better name since you know better about the contexts.
def convert(unplanned, planned, emerg):
chain = (unplanned, planned, emerg)
names = map(lambda lst: [d['service__name'] for d in lst], chain)
sums = map(lambda lst: [d['service_sum'] for d in lst], chain)
ds = [dict(zip(n, s)) for n,s in zip(names, sums)]
unique_names = set([])
unique_names = reduce(unique_names.union,names)
results = []
for n in unique_names:
s = []
for i in range(3):
s.append(ds[i].get(n,0))
results.append((n, tuple(s)))
return results
print convert(unplanned, planned, emerg)
The output at my machine is
[(u'Internet', (0, 0, 1)), (u'Peoplesoft', (2, 4, 0)), (u'Email', (4, 2, 0)), (u'Gopher', (0, 2, 0))]
Upvotes: 0
Reputation: 9323
Just use a dict, then convert it into a list afterwards:
some_list = [{'service__name': u'Email', 'service_sum': 4}, {'service__name': u'Email', 'service_sum': 1}, {'service__name': u'Network', 'service_sum': 0}]
def combine(list):
combined = {}
for item in list:
if item['service__name'] not in combined:
combined[item['service__name']] = []
combined[item['service__name']].append(item['service_sum'])
return combined.items()
combine(some_list) # [(u'Email', [4, 1]), (u'Network', [0])]
combine(unplanned)
combine(emerg + planned)
.....
Here's the version of the function that uses defaultdict:
def combine(list):
from collections import defaultdict
combined = defaultdict(list)
for item in list:
combined[item['service__name']].append(item['service_sum'])
return combined.items()
A little cleaner, but there's an unnecessary import, and a few other problems with it that may pop up in the future if the function definition is changed (see comments).
Upvotes: 2
Reputation: 310049
It seems like you could do something like:
output = []
for dicts in zip(unplanned,planned,emerg):
output.append(('Email',tuple(d['service_sum'] if d['service__name'] == 'Email' else 0 for d in dicts)))
Upvotes: 1