Python使用组合来对字典中列表中的元组中的值求和?

时间:2017-04-14 16:01:14

标签: python tuples combinations

我试图从字典中的元组列表中总结值的组合。例如,我的字典包含:

dict = {1: [(2, 2), (4, 3), (6, 1), (7, 1), (8, 3)], 2: [(4, 1), (5, 3), (1, 2)],...} 

继续进行多项录入。我尝试在最多为4的组合中为每个条目的元组的第二个值求和。因此对于条目1,所需的输出将是:

{1: [(2, 6, 3), (2, 7, 3), (4, 6, 4), (4, 7, 4), (6, 7, 2), (8, 6, 4), (8, 7, 4)]

此元组中的第三个值是前一个元组的第二个值的组合之和,并且该元组的第一个和第二个值是前一个元组的相关第一个值。

我尝试过以下代码:

for key, value in dict.items():
    object1 = key
    mylist = value
    for tup in mylist:
         object2 = tup[0]
         pair = tup[1]
         combo = itertools.combinations(tup[1],2)
         sum = {k:sum(j for _,j in v) for k,v in combo}
         if sum <= 4:
             print(sum)

我收到错误

'numpy.float64' object is not iterable

我认为我的错误来自&#34; combo&#34;可能还有我对itertools的使用。我不确定我是否只需要修复我的代码的这一部分,或者我是否偏离了我的方法。

1 个答案:

答案 0 :(得分:1)

是的,您可以使用itertools.combinations执行此操作,但必须将正确的参数传递给它。 :)您需要将元组列表传递给它,以便它可以生成元组对。你可以用理解来做到这一点,但我认为使用传统的for循环可以更容易阅读。

正如其他人所提到的,除了没有将正确的内容传递给combinations之外,您的代码还存在其他问题。主要的一点是,您要为名称sum分配字典,这会影响您尝试使用的sum内置函数。并且您还尝试将该字典与整数4进行比较,这没有多大意义。 :)

无论如何,这里有一些代码可以满足您的需求。请注意,在您的预期输出中,您混淆了最后两个元组:(8, 6, 4)(8, 7, 4)应分别为(6, 8, 4)(7, 8, 4)

from itertools import combinations

a = {
    1: [(2, 2), (4, 3), (6, 1), (7, 1), (8, 3)], 
    2: [(4, 1), (5, 3), (1, 2)],
}

new_dict = {}

for k, seq in a.items():
    c = []
    for (u,v), (x,y) in combinations(seq, 2):
        total = v + y
        if total <= 4:
            c.append((u, x, total))
    new_dict[k] = c

for k, seq in new_dict.items():
    print(k, seq)

<强>输出

1 [(2, 6, 3), (2, 7, 3), (4, 6, 4), (4, 7, 4), (6, 7, 2), (6, 8, 4), (7, 8, 4)]
2 [(4, 5, 4), (4, 1, 3)]

combinations(seq, 2)产生元组对,我们可以用

将这些元组解压缩到它们各自的数字中
for (u,v), (x,y) in combinations(seq, 2):

我们可以做类似

的事情
for t0, t1 in combinations(seq, 2):

然后在单独的步骤中解压缩t0t1元组,或者仅使用索引来获取其项目。例如,

for t0, t1 in combinations(seq, 2):
    total = t0[1] + t1[1]
    if total <= 4:
        c.append((t[0], t[1], total))

但我认为以前的方式不那么混乱。

但如果你坚持用理解来做这一切,你可以:

new_dict = {k: [(u, x, v+y) for (u,v), (x,y) in combinations(seq, 2) if v+y <= 4]
    for k, seq in a.items()}

请注意,这比以前的版本效率低,因为它会为通过v+y测试的每个组合计算两次v+y <= 4