2015-10-22 6 views
5

У меня есть два списка словарей.Вычитать значения из списка словарей из другого списка словарей

foo = [{'Tom': 8.2}, {'Bob': 16.7}, {'Mike': 11.6}] 
bar = [{'Tom': 4.2}, {'Bob': 6.7}, {'Mike': 10.2}] 

Вычитание а и Ь должны быть обновлены в обув:

foo = [{'Tom': 4.0}, {'Bob': 10.0}, {'Mike': 1.4}] 

Теперь я попытался это с двумя петлями и zip -функции:

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) 

Я получаю TypeError: 'float' object is not iterable , Где моя ошибка?

+0

Ваши структуры данных неправы. 'foo' и' bar', вероятно, не должны быть списками словарей. Или, по крайней мере, словари не должны иметь разных ключей. Что вы представляете? Что вам нужно сделать с данными? –

ответ

3

Вы были очень близки. Проблема заключалась в понимании списка, которое у вас было в понимании словаря. mydict[k], mydictcorr[k] оба возвращались поплавками, но вы пытались перебрать их [x-y for x, y in mydict[k], mydictcorr[k]].

Это будет работать для вас:

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 

Или как гораздо менее читаемым однострочника (потому что я хотел бы видеть, если я мог):

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)] 

Сказав это, вы можете все еще видят некоторые странные результаты, когда вы вычитаете поплавки. Например, {'Tom': 3.999999999999999}. Вы можете обернуть v - sub_dict.get(k, 0) в призыв к раунду.

+0

Работает как шарм, спасибо Морган! – GeoEki

+0

@GeoEki Glad Я мог бы помочь! –

0

Вы можете создавать словари foo и bar и список использования понимания:

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]) 

Выход:

{'Bob': 10.0, 'Mike': 1.4, 'Tom': 4.0} 
0

Если вы хотите dicts в foo обновляемой вы можете сделать это прямо как списки и dicts являются неизменными:

def sub(a, b): 
    for d1, d2 in zip(a, b): 
     for k, v in d2.items(): 
      d1[k] -= v 

Любые изменения будут отражены в вашем списке, который просто хранит ссылки на ваш 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}] 

Как вы можете видеть, вы также должны быть осведомлены о floating-point-arithmetic-issues-and-limitations