I would like to sum across keys of dictionaries nested within a list using the functools.reduce
function
I can accomplish this WITHOUT the functools.reduce
function with the following simple program:
dict1 = {'a': '1', 'b': '2'}
dict2 = {'a': '5', 'b': '0'}
dict3 = {'a': '7', 'b': '3'}
data_list = [dict1, dict2, dict3]
total_a = 0
total_b = 0
for record in data_list:
total_a += eval(record['a'])
total_b += eval(record['b'])
print(total_a)
print(total_b)
As I said however, I would like to produce the same results using the functools.reduce
method instead.
Here is my attempt at using functools.reduce
with a lambda expression:
from functools import reduce
dict1 = {'a': '1', 'b': '2'}
dict2 = {'a': '5', 'b': '0'}
dict3 = {'a': '7', 'b': '3'}
data_list = [dict1, dict2, dict3]
total_a = reduce(lambda x, y: int(x['a']) + int(y['a']),data_list)
total_b = reduce(lambda x, y: int(x['b']) + int(y['b']),data_list )
print(total_a)
print(total_b)
Unfortunately, I get the following error and do not know why:
TypeError: 'int' object is not subscriptable
Does someone know why I am getting this error?
TypeError: 'int' object is not subscriptable
Does someone know why I am getting this error?
First, let's reduce (pun intended) the sample to a minimum:
>>> from functools import reduce
>>> data = [{"a": 1}, {"a": 2}, {"a": 3}]
>>> reduce(lambda x, y: x["a"] + y["a"], data)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: 'int' object is not subscriptable
Same error. But observe this:
>>> reduce(lambda x, y: x["a"] + y["a"], data[:2])
3
That's working. So what's going on? For simplification, let's assign the lambda expression to a variable:
f = lambda x, y: x['a'] + y['a']
Reduce combines the input like this:
# Example: reduce(lambda x, y: x["a"] + y["a"], data[:2])
>>> f(data[0], data[1])
# which evaluates in steps like this:
>>> data[0]["a"] + data[1]["a"]
>>> 1 + 2
>>> 3
But what's happening when reducing the full list? This evaluates to
# Example: reduce(lambda x, y: x["a"] + y["a"], data)
>>> f(f(data[0], data[1]), data[2])
# which evaluates in steps like this:
>>> f(data[0]["a"] + data[1]["a"], data[2])
>>> f(1 + 2, data[2])
>>> f(3, data[2])
>>> 3["a"] + data[2]["a"]
So this errors out because it tries to access item "a"
from the integer 3.
Basically: The output of the function passed to reduce must be acceptable as its first parameter. In your example, the lambda expects a dictionary as its first parameter and returns an integer.