【问题标题】:Print a list of every combination of dictionary keys with the associated sum of the key values to the right打印字典键的每个组合的列表以及右侧键值的相关总和
【发布时间】:2017-01-03 16:07:32
【问题描述】:

我有几个字典,我想打印一个表格,其中每一行都是所有字典中键的唯一组合。对于每一行,我还想打印该特定组合中键的值的总和。

所以,如果我有这些词典:

dict1 = {"Main": 8, "Optional": 6, "Obscure": 4}
dict2 = {"Global": 8, "Regional": 4, "Local": 2}
...

输出如下所示(按总和从高到低排序):

Main, Global, 16
Optional, Global, 14
Main, Regional, 12
Obscure, Global, 12
Main, Local, 10
Optional, Regional, 10
Optional, Local, 8
Obscure, Regional, 8
Obscure, Local, 6

根据我的阅读,itertools.product 将是我正在寻找的,但现有的问题都不是我的用例,我什至都在努力开始。

任何帮助将不胜感激。

谢谢

【问题讨论】:

    标签: python dictionary product itertools cartesian-product


    【解决方案1】:

    你没看错。只需添加sorted()

    from itertools import product
    from operator import itemgetter
    
    results = [(k1, k2, dict1[k1] + dict2[k2])
               for k1, k2 in product(dict1.keys(), dict2.keys())]
    
    for k1, k2, sum_ in sorted(results, key=itemgetter(2), reverse=True): 
        print(k1, k2, sum_, sep=', ')
    

    【讨论】:

    • 这非常有效!我有很多字典,所以我不得不添加额外的变量并调整 itemgetter 值,但其他方面都很完美。非常感谢:)
    【解决方案2】:

    我认为这会是这样的:

    import itertools
    
    dict1 = {"Main": 8, "Optional": 6, "Obscure": 4}
    dict2 = {"Global": 8, "Regional": 4, "Local": 2}
    
    merged = {'{}, {}'.format(prod[0], prod[1]): dict1[prod[0]] + dict2[prod[1]] 
              for prod in itertools.product(dict1, dict2)}
    
    for k, v in merged.items():
        print('{}: {}'.format(k, v))
    

    输出:

    Optional, Regional: 10
    Main, Regional: 12
    Optional, Local: 8
    Main, Global: 16
    Optional, Global: 14
    Main, Local: 10
    Obscure, Regional: 8
    Obscure, Global: 12
    Obscure, Local: 6
    

    【讨论】:

      【解决方案3】:

      在字典 items() 上使用 itertools 中的 product,您可以同时获取键和值,通过键值对的组合,您可以非常简单地构造最终结果:

      from itertools import product
      sorted([(k1, k2, v1+v2) for (k1, v1), (k2, v2) in product(dict1.items(), dict2.items())], \
             key = lambda x: x[2], reverse=True)
      
      # [('Main', 'Global', 16),
      #  ('Optional', 'Global', 14),
      #  ('Obscure', 'Global', 12),
      #  ('Main', 'Regional', 12),
      #  ('Main', 'Local', 10),
      #  ('Optional', 'Regional', 10),
      #  ('Obscure', 'Regional', 8),
      #  ('Optional', 'Local', 8),
      #  ('Obscure', 'Local', 6)]
      

      【讨论】:

      • 这个答案比迄今为止发布的其他答案更有效,因为它通过使用.items() 避免了不必要的dict 查找(尽管您应该在Py2 上使用.viewitems() 以最小化临时lists)和不必要的tuple 索引通过使用解包命名变量。需要添加排序步骤(operator.itemgetter(2) 用于 key 函数)。
      • @ShadowRanger 虽然是真的,但差异很小(例如 2.29µs 与 2.33µs,py3)。但是使用items() 和解包是一个不错的选择。
      【解决方案4】:

      此方法旨在支持可变数量的字典。您将字典传递给 get_product_sums() 方法,然后该方法从字典元组创建笛卡尔积。

      然后我们遍历我们的新subitem 以通过在我们的flattened 中查找来计算总和,这现在只是一个一维字典。然后我们按总和排序,并为我们的最终 result 返回一个排序后的元组列表。

      from itertools import product
      
      def get_product_sums(* args):
          result = []
          flattened = {k:v for d in args for k, v in d.items()}
          for subitem in product(* args, repeat=1):
              data = subitem + (sum(flattened[key] for key in subitem),)  
              result.append(data)
          return sorted(result, key=lambda x: x[-1], reverse=True)
      

      样本输出:

      >>> dict1 = {"Global": 8, "Regional": 4, "Local": 2} 
      >>> dict2 = {"Main": 8, "Optional": 6, "Obscure": 4}
      >>> for item in get_product_sums(dict1, dict2):
      ...     print ', '.join(str(element) for element in item)
      Global, Main, 16
      Global, Optional, 14
      Global, Obscure, 12
      Regional, Main, 12
      Local, Main, 10
      Regional, Optional, 10
      Local, Optional, 8
      Regional, Obscure, 8
      Local, Obscure, 6
      

      【讨论】:

      • *args 可以用来代替字典元组
      • @DiegoAllen 当然可以!我将其保留为元组,因为我不确定他以哪种方式处理数据。
      猜你喜欢
      • 2021-08-14
      • 1970-01-01
      • 2020-01-04
      • 1970-01-01
      • 1970-01-01
      • 2018-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多