【问题标题】:Using 'reduce' on a list of dictionaries在字典列表上使用“减少”
【发布时间】:2017-07-16 03:19:32
【问题描述】:

我正在尝试编写一个简单的 Python 函数,它将所有具有 likes 键的值相加。我正在为这项任务使用函数式编程。因此,我需要使用 list-comprehensionmapfilterreduce。在这种情况下,我认为 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' object is not subscriptable。对我来说,这个错误毫无意义。如果reduce 真的在遍历给定的参数,那么传递给 lambda 函数的每个项目都应该是一个字典 - 每个项目肯定都有一个 likes 键。问题是什么,这个 Python 错误究竟是什么意思?

【问题讨论】:

    标签: python dictionary functional-programming itertools


    【解决方案1】:

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

    为避免这种情况,您可以首先执行列表或生成器理解,以从各种 dicts 中提取“喜欢”处的所有值,然后在这些值上减少 operator.add。或者只使用 sum。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        考虑reduce 的工作原理。 x 是累加器变量,设置为前一个函数的返回值。

        第一次迭代

        lambda x, y: x["likes"] + y["likes"] = 40
        

        第二次迭代

        lambda 40, y: 40["likes"] + y["likes"] = ???
        

        【讨论】:

          【解决方案4】:

          对我来说,这个错误毫无意义。如果 reduce 是真正遍历给定参数,那么传入 lambda 函数的每个项目都应该是一个字典

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

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

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

          0 是 reduce 的“初始化器”参数,它为 x 提供第一个值。现在在每次调用中,x 是运行总和,y 是下一个字典。

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

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

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

          【讨论】:

            【解决方案5】:

            在您的代码 sn-p reduce(lambda x, y: x["likes"] + y["likes"], msgs), x 变量最初是列表 msgs (dict) 的第一个元素,但在第二次迭代中它将是 "likes" (@987654326) 的总和@)。

            所以,总结喜欢使用reduce函数docinitializer参数。

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

            但我相信,使用sum 是一种更 Pythonic 的方式:

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

            【讨论】:

              猜你喜欢
              • 2021-03-03
              • 2014-05-16
              • 1970-01-01
              • 2021-12-30
              • 2021-09-07
              • 2013-12-30
              • 2020-04-03
              • 2012-05-03
              • 1970-01-01
              相关资源
              最近更新 更多