列表或字典列表中的所有组合

时间:2018-11-08 15:51:15

标签: python dictionary tuples

使用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个整数的列表。 / p>

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

1 个答案:

答案 0 :(得分:0)

我认为解决此问题的最简单方法是使用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来获取每种可能的组合大小的每种可能的组合,对其求和,然后将其保存到输出dict

由于您要存储每个值的硬币的所有可能组合,因此可以将dict中的每个项目变成collections.Counter中的setset仅存储唯一的硬币计数:

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()})

对于每个硬币价值总和,将打印出dict中的set。每个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))}}