Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subtract values from list of dictionaries from another list of dictionaries

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?

like image 408
GeoEki Avatar asked Oct 19 '22 23:10

GeoEki


1 Answers

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.

like image 65
Morgan Thrapp Avatar answered Oct 22 '22 10:10

Morgan Thrapp