【问题标题】:Add Counters keeping zero values添加保持零值的计数器
【发布时间】:2020-11-14 00:50:02
【问题描述】:

我尝试将其他字典中存在的键的值与此代码相加:

import functools
import operator
import collections

my_dict = [{'a':0, 'b':1, 'c':5}, {'b':3, 'c':2}, {'b':1, 'c':1}]
sum_key_value = functools.reduce(operator.add, map(collections.Counter, my_dict))

print(sum_key_value)

# Output
# Counter({'c': 8, 'b': 5})

我的问题是,如果我希望输出保留所有字典键,即使在我的情况下该键没有出现在像 a 这样的所有字典中,不使用循环的最佳方法是什么?

【问题讨论】:

标签: python dictionary


【解决方案1】:

使用 for 循环有很多不错的方法,但由于您特别想避免 for 循环,所以这里有一种方法:

sum_key_value = dict(functools.reduce(lambda a, b: a.update(b) or a,
                     my_dict, collections.Counter()))

所以这里发生的事情是您创建一个计数器,并使用它来累积值。

【讨论】:

    【解决方案2】:

    在这里,最直接的方法是循环。您可能有键出现在列表中任何位置的字典中(例如:第三个可能有键“e”),因此您至少需要一个循环来获得键的总数。然后你可以再次遍历所有字典来总结这些值。为它创建一个自己的函数,您可以调用它而无需再关心循环。

    def sum_it_up(dictlist):
        outdic = {}
        for d in dictlist:
            for k in d.keys():
                outdic[k] = 0
        for d in dictlist:
            for k in d.keys():
                outdic[k]+=d[k]
        return outdic
    
    my_dict = [{'a':0, 'b':1, 'c':5}, {'b':3, 'c':2}, {'b':1, 'c':1}]
    sum_key_value = sum_it_up(my_dict)
    
    

    【讨论】:

      【解决方案3】:

      如 cmets 中所述,添加 Counter 对象将删除非正键

      所以问题不在于最终不是所有键的联合(以及添加公共值),因为这确实是行为,看看我们是否设置了a:2

      my_dict = [{'a':2, 'b':1, 'c':5}, {'b':3, 'c':2}, {'b':1, 'c':1}]
      functools.reduce(operator.add, map(Counter, my_dict))
      # Counter({'a': 2, 'b': 5, 'c': 8})
      

      但是,如问题所示,根据当前的实现,当添加 Counter 对象时,非正值 (a:0) 会被删除。

      如果您真的想为此使用 Counter,您可以稍微调整 current implementation 覆盖 __add__ 以获得预期的行为:

      class Counter_tweaked(Counter):
          def __add__(self, other):
                  if not isinstance(other, Counter):
                      return NotImplemented
                  result = Counter_tweaked()
                  for elem, count in self.items():
                      newcount = count + other[elem]
                      result[elem] = newcount
                  for elem, count in other.items():
                      if elem not in self:
                          result[elem] = count
                  return result
      

      functools.reduce(operator.add, map(Counter_tweaked, my_dict))
      # Counter_tweaked({'a': 0, 'b': 5, 'c': 8})
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-05-02
        • 1970-01-01
        • 1970-01-01
        • 2023-04-10
        • 1970-01-01
        • 2021-06-15
        • 1970-01-01
        相关资源
        最近更新 更多