【问题标题】:All combinations in list of list or dictionary列表或字典列表中的所有组合
【发布时间】:2018-11-08 15:51:14
【问题描述】:

使用 Python:

我有一本字典,其中的“键”代表硬币的价值。而“价值”代表那枚硬币的数量。

如:

dict =  {2: [0], 1: [0], 0.5: [0], 0.2: [0], 0.1: [0], 0.05: [1], 0.02: [1, 1, 1, 1], 0.01: [1, 1, 1]}

或

dict = {2: [], 1: [], 0.5: [], 0.2: [], 0.1: [], 0.05: [1], 0.02: [1, 1, 1, 1], 0.01: [1, 1, 1]}

或

dict = {2: 0, 1: 0, 0.5: 0, 0.2: 0, 0.1: 0, 0.05: 1, 0.02: 4, 0.01: 3}

(我不确定哪个最好用 - 它也可以表示为 8 个整数的列表,例如 [0,0,0,0,0,1,4,3] 或列表例如 [[],[],[],[],[],[1],[1,1,1,1],[1,1,1]])

我想创建一个字典,显示不同硬币的所有可能组合,其中“键”是硬币的总价值,“价值”是代表每个硬币数量的 8 个整数的列表。

编辑:我意识到我想要用字典做不可能的事情,因为你不能对单个键名进行多个分配:如何使用函数 itertools.combinations(iterable, r) 返回一个元组列表?

【问题讨论】:

  • 太棒了!你有什么办法解决这个问题?
  • 到目前为止我已经尝试过了,但我不知道解决方案是什么 tbh import itertools for key in dictionary: itertools.combinations(dictionary[key] , len(dictionary[key]))跨度>

标签: python dictionary tuples


【解决方案1】:

我认为解决此问题的最简单方法是使用itertools.combinations。

要使用它,您首先需要将 dict 的硬币数量转换为 list 的硬币数量:

coins = {2: 0, 1: 0, 0.5: 0, 0.2: 0, 0.1: 0, 0.05: 1, 0.02: 4, 0.01: 3}
# stores a list of all coin values, ie [0.2, 0.2, 1] if one has two 20c and 1 $1
coin_list = []
for value, count in coins.items():
    if count > 0:
        coin_list += [value] * count

然后,可以使用itertools.combinations 获取每种可能组合大小的每种可能组合,将其相加,并将 if 保存到输出 dict。

由于您想为每个值存储所有可能的硬币组合,您可以将dict 中的每个项目转换为set 的collections.Counter。 set 只会存储唯一的硬币数量:

import itertools
import collections
output_dict = dict()
for comb_size in range(len(coin_list)):
    # gets every combination of every size from coin_list
    for combination in itertools.combinations(coin_list, comb_size):
        # sums up all coins in combination
        value = sum(combination)
        # get the set of existing coins for value/create if it doesn't exist
        value_set = output_dict.get(value, set())
        # collections.Counter counts up each coin in a combination
        counter = collections.Counter(combination)
        # we need to convert counter to a hashable form to add it to a set()
        value_set.add(tuple(sorted(counter.items())))
        output_dict[value] = value_set

最后,因为将浮点数相加会导致奇怪的结果(如0.1 + 0.2 = 0.300000001),打印时您可以将总和的值四舍五入到最接近的分(并使用模块pprint 使格式更好):

import pprint
pprint.pprint({round(x, 2): y for x,y in output_dict.items()})

这将为每个硬币价值总和打印出set 的dict。每个set 包含tuples 对(硬币价值,硬币数量),即对于 3 美分,一个可以有 3 * 1c 硬币 (((0.01, 3),)),或 1c + 2c (((0.01, 1), (0.02, 1))):

{0: {()},
 0.01: {((0.01, 1),)},
 0.02: {((0.02, 1),), ((0.01, 2),)},
 0.03: {((0.01, 3),), ((0.01, 1), (0.02, 1))},
 0.04: {((0.02, 2),), ((0.01, 2), (0.02, 1))},
 0.05: {((0.01, 1), (0.02, 2)), ((0.05, 1),), ((0.01, 3), (0.02, 1))},
 0.06: {((0.02, 3),)},
 0.07: {((0.01, 1), (0.02, 3))},
 0.08: {((0.01, 2), (0.02, 3))},
 0.09: {((0.01, 3), (0.02, 3))},
 0.1: {((0.01, 3), (0.02, 1), (0.05, 1)), ((0.01, 2), (0.02, 4))},
 0.11: {((0.01, 3), (0.02, 4))},
 0.12: {((0.01, 3), (0.02, 2), (0.05, 1))},
 0.13: {((0.01, 2), (0.02, 3), (0.05, 1)), ((0.02, 4), (0.05, 1))},
 0.14: {((0.01, 1), (0.02, 4), (0.05, 1)), ((0.01, 3), (0.02, 3), (0.05, 1))},
 0.15: {((0.01, 2), (0.02, 4), (0.05, 1))}}

【讨论】:

  • 我刚刚意识到这是错误的(至少对于我的意图),例如“关键”0.07 应该出现两次:(0.02, 0.02,0.02,0.1) 和 (0.5, 0.2)。由于您不能对一个键名进行多个分配,我意识到用字典是不可能的。如何使用 itertools 中的相同函数来创建元组列表,以便您可以拥有多个合计相同值的元组?
猜你喜欢
  • 2020-07-16
  • 1970-01-01
  • 2017-06-11
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 2013-02-19
相关资源
最近更新 更多