Python 使用';减少';在字典列表上

Python 使用';减少';在字典列表上,python,dictionary,functional-programming,itertools,Python,Dictionary,Functional Programming,Itertools,我正在尝试编写一个简单的Python函数,该函数对所有具有键的值进行求和。我正在为这项任务做函数式编程。因此,我需要使用列表理解、map、filter或reduce。在这种情况下,我认为reduce是一个合理的选择 def sum_favorites(msgs): num_favorites = reduce(lambda x, y: x["likes"] + y["likes"], msgs) return num_favorites content1 = {"like

我正在尝试编写一个简单的Python函数,该函数对所有具有键的值进行求和。我正在为这项任务做函数式编程。因此,我需要使用列表理解、
map
filter
reduce
。在这种情况下,我认为reduce是一个合理的选择

def sum_favorites(msgs):
     num_favorites = reduce(lambda x, y: x["likes"] + y["likes"], msgs)
     return num_favorites


content1 = {"likes": 32, ...}
content2 = {"likes": 8, ...}
content3 = {"likes": 16, ...}
contents = [content1, content2, content3]
print(sum_favorites(contents)) 

问题在于我何时实际运行代码。我似乎收到了如下信息:TypeError:“int”对象不可下标。对我来说,这个错误毫无意义。如果
reduce
确实在迭代给定的参数,那么传递到lambda函数中的每个项都应该是一个字典,并且每个项中肯定都有一个likes键。问题是什么,这个Python错误到底意味着什么?

根据reduce的具体实现方式,在reduce的第二次迭代中,传递给lambda的一个操作数将不是dict,而是迄今为止计算的总和。这让你看到了你所看到的错误


为了避免这种情况,您可以首先进行列表或生成器理解,从各种dict中提取“likes”处的所有值,然后减少
运算符。在这些dict上添加
。或者只使用sum。

阅读Paul的回答后,我意识到为了确保始终对一致的数据类型进行汇总,我必须启动
reduce
以使用int表示“x”,使用dictionary表示“y”。因此,

def average_favorites(tweets):
    num_favorites = reduce(lambda x, y: x + y["favorites"], tweets, 0)
    return num_favorites

考虑一下
reduce
是如何工作的
x
是设置为上一个函数返回值的累加器变量

第一次迭代

lambda x, y: x["likes"] + y["likes"] = 40
lambda 40, y: 40["likes"] + y["likes"] = ???
第二次迭代

lambda x, y: x["likes"] + y["likes"] = 40
lambda 40, y: 40["likes"] + y["likes"] = ???
对我来说,这个错误毫无意义。如果reduce确实在迭代给定的参数,那么传入lambda函数的每个项都应该是一个字典

否,传递给lambda的第一个参数(对于除第一个调用以外的所有调用)是上一次调用lambda的返回值。您的函数返回一个数字,因此调用该函数时,
x
是一个数字,而不是字典

有两种方法可以解决这个问题。更直接的可能是:

num_favorites = reduce(lambda x, y: x + y['likes'], msgs, 0)
0
是要reduce的“initializer”参数,它为
x
提供第一个值。现在,在每个调用中,
x
是运行总和,
y
是下一个字典

另一种方式,只是为了证明它是可以做到的,是:

result = reduce(lambda x, y: { 'likes': x['likes'] + y['likes'] }, msgs)
num_favorites = result['likes']

这使得lambda的返回值是一个带有
likes
键的dict,就像它的参数一样,所以我们一直在使用相同的类型。在这种情况下,它是不必要和浪费的,但是如果您聚合多个键,它可能是一种有趣的方法。

在您的代码片段
reduce(lambda x,y:x[“likes”]+y[“likes”],msgs)
x
变量首先是列表msgs的第一个元素(
dict
),但在第二次迭代中,它将是
“likes”
int
)的总和

因此,为了求和,使用
reduce
函数的
初始值设定项
参数

但我相信,使用
sum
是一种更具python风格的方式:

def sum_favorites(msgs):
    num_favorites = sum(i['likes'] for i in msgs)
    return num_favorites