Using 'reduce' on a list of dictionaries
To me, this error makes no sense. If reduce is truly iterating through the given parameter, then each item passed into the lambda-function should be a dictionary
No, the first parameter passed to the lambda (for all calls except the first) is the return value from the previous call to the lambda. Your function returns a number, so it will be called with x
being a number, not a dictionary.
There are two ways to deal with this. The probably more straightforward one is:
num_favorites = reduce(lambda x, y: x + y['likes'], msgs, 0)
The 0
is the "initializer" argument to reduce, which provides the first value for x
. Now in each call, x
is the running sum and y
is the next dictionary.
Another way, just to show that it can be done, is:
result = reduce(lambda x, y: { 'likes': x['likes'] + y['likes'] }, msgs)
num_favorites = result['likes']
which makes the return value of the lambda be a dict with a likes
key, just like its arguments, so we're working with the same type the whole way through. In this case it's unnecessary and wasteful, but if you were aggregating more than one key, it might be an interesting approach.
In your code snippet reduce(lambda x, y: x["likes"] + y["likes"], msgs)
, x
variable at first is the first element of list msgs (dict
), but at the second iteration it'll be a sum of "likes"
(int
).
So, to sum the likes use the initializer
argument of reduce
function doc.
def sum_favorites(msgs):
num_favorites = reduce(lambda x, y: x + y["likes"], msgs, 0)
return num_favorites
But I believe, using sum
is a more pythonic way:
def sum_favorites(msgs):
num_favorites = sum(i['likes'] for i in msgs)
return num_favorites