Reputation: 437
I have two lists of dictionaries.
foo = [{'Tom': 8.2}, {'Bob': 16.7}, {'Mike': 11.6}]
bar = [{'Tom': 4.2}, {'Bob': 6.7}, {'Mike': 10.2}]
The subtraction of a and b should be updated in foo:
foo = [{'Tom': 4.0}, {'Bob': 10.0}, {'Mike': 1.4}]
Now I tried this with two loops and the zip
-function:
def sub(a,b):
for mydict,mydictcorr in zip(a,b):
{k:[x-y for x, y in mydict[k], mydictcorr[k]] for k in mydict}
return mydict
print sub(foo,bar)
I get a TypeError: 'float' object is not iterable
. Where's my mistake?
Upvotes: 5
Views: 1511
Reputation: 180391
If you want the dicts in foo
updated you can do it directly as lists and dicts are both immutable:
def sub(a, b):
for d1, d2 in zip(a, b):
for k, v in d2.items():
d1[k] -= v
Any changes will be reflected in your list which just holds references to your dicst:
In [2]: foo
Out[2]: [{'Tom': 8.2}, {'Bob': 16.7}, {'Mike': 11.6}]
In [3]: sub(foo, bar)
In [4]: foo
Out[4]: [{'Tom': 3.999999999999999}, {'Bob': 10.0}, {'Mike': 1.4000000000000004}]
As you can see you also need to be aware of floating-point-arithmetic-issues-and-limitations
Upvotes: 0
Reputation: 10135
You can build dictionaries from foo
and bar
and use list comprehension:
a = dict([next(x.iteritems()) for x in foo])
b = dict([next(x.iteritems()) for x in bar])
sub_dict = dict([(key, round(a[key] - b.get(key, 0), 1)) for key in a])
Output:
{'Bob': 10.0, 'Mike': 1.4, 'Tom': 4.0}
Upvotes: 0
Reputation: 9986
You were very close. The issue was the list comprehension you had in your dictionary comprehension. mydict[k], mydictcorr[k]
were both returning floats, but you were trying to iterate over them [x-y for x, y in mydict[k], mydictcorr[k]]
.
This will work for you:
def sub(base, subtract):
corrected = []
for base_dict, sub_dict in zip(base, subtract):
corrected.append({k: v - sub_dict.get(k, 0) for k, v in base_dict.items()})
return corrected
Or as a much less readable one-liner (because I wanted to see if I could):
def sub(base, subtract):
return [{k: v - sub_dict.get(k, 0) for k, v in base_dict.items()} for base_dict, sub_dict in zip(base, subtract)]
Having said that, you may still see some weird results when you subtract floats. Eg, {'Tom': 3.999999999999999}
. You may want to wrap v - sub_dict.get(k, 0)
in a call to round.
Upvotes: 3