0

我有一个元组列表如下

[(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]

现在我需要这样的东西

  1. 在上面的列表中,每个元素都是一个元组,元组中的第一项是索引,第二项是一个值。
  2. 我们需要将所有索引相等的元组值相乘,然后将所有索引的所有乘法结果相加。
  3. 如果只有一次具有特定索引的元组,我们必须为此将乘法结果设为零。这意味着元组对最终总和没有贡献。

如果有人可以帮助我,我将非常感激。我是python新手,所以很难。

4

7 回答 7

3

这是一种方法。用于itertools.groupby创建每个索引对应的组,相乘和相加

from operator import itemgetter, mul
from itertools import groupby
z = [(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]
z = sorted(z, key=itemgetter(0))
z = groupby(z, key=itemgetter(0))
z = ((key, list(value for (key, value) in groups)) for (key, groups) in z)
z = ((key, reduce(mul, values, 1)) for (key, values) in z if len(values) > 1)
z = sum(value for (key, value) in z)
print z
7425
于 2013-05-29T16:37:39.093 回答
1

将所有元组转移到一个字典中,其中键是第一个元素,值是第二个元素的列表。过滤包含多个元素的值的字典。用于reduce()将每个值的元素相乘,sum()并将所有乘积相加。

于 2013-05-29T16:20:27.397 回答
0

上面的答案很好,但不容易理解。不幸的是,如 1_CR 所指出的那样,z从后面开始打印其中一个可读列表将消耗迭代器。groupby这又是解决方案,但打印了中间步骤。从逻辑上讲,从z3需要开始的所有步骤在每次打印后都需要重新完成。

from operator import itemgetter, mul
from itertools import groupby
from functools import reduce
import copy

z1 = [(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]
print('data:   ', z1)
z2 = sorted(z1, key=itemgetter(0))
print('sorted: ', z2)
z3 = groupby(z2, key=itemgetter(0))
print('grouped:', [(x, list(y)) for x,y  in z3])
z3 = groupby(z2, key=itemgetter(0))
z4 = ((key, list(value for (key, value) in groups)) for (key, groups) in z3)
print('lumped: ', list(z4))
z3 = groupby(z2, key=itemgetter(0))
z4 = ((key, list(value for (key, value) in groups)) for (key, groups) in z3)
z5 = ((key, reduce(mul, values, 1)) for (key, values) in z4 if len(values) > 1)
print('reduced:', list(z5))
z3 = groupby(z2, key=itemgetter(0))
z4 = ((key, list(value for (key, value) in groups)) for (key, groups) in z3)
z5 = ((key, reduce(mul, values, 1)) for (key, values) in z4 if len(values) > 1)
z6 = sum(value for (key, value) in z5)
print('sum:    ', z6)

这就是这一切的回报。我认为这真的有助于理解发生了什么。函数式编程可以很有趣,只要您了解会发生什么。

data:    [(1, 4), (3, 5), (2, 9), (6, 23), (3, 21), (2, 66), (5, 20), (1, 33), (3, 55), (1, 8)]
sorted:  [(1, 4), (1, 33), (1, 8), (2, 9), (2, 66), (3, 5), (3, 21), (3, 55), (5, 20), (6, 23)]
grouped: [(1, [(1, 4), (1, 33), (1, 8)]), (2, [(2, 9), (2, 66)]), (3, [(3, 5), (3, 21), (3, 55)]), (5, [(5, 20)]), (6, [(6, 23)])]
lumped:  [(1, [4, 33, 8]), (2, [9, 66]), (3, [5, 21, 55]), (5, [20]), (6, [23])]
reduced: [(1, 1056), (2, 594), (3, 5775)]
sum:     7425
于 2013-05-29T18:10:19.137 回答
0

另一种(略有不同)的方式。我们将元素收集到一个字典中,其中每个value都是字典

import operator,collections
s=[(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]
s_d = collections.defaultdict(list)
for x in s: 
    s_d[x[0]].append(x[1])

s_d 现在是

>>> s_d
defaultdict(<type 'list'>, {1: [4, 33, 8], 2: [9, 66], 3: [5, 21, 55], 5: [20], 6: [23]})

现在对于每个键,如果值字典的长度大于 1,我们将值相乘,否则返回 0

>>>map(lambda y: reduce(operator.mul,y[1],0) if len(y[1])>1 else 0,s_d.items())
[1056, 594, 5775, 0, 0]

但是你想要总和,所以我们求和

>>>sum(map(lambda y: reduce(operator.mul,y[1],1) if len(y[1])>1 else 0,s_d.items()))
7425
于 2013-05-29T17:13:57.587 回答
0

这是一个简单的程序版本:

tups=[(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]

di={}
for t in tups:
    di.setdefault(t[0],[]).append(t[1])

ans=0
for k in di:
    if len(di[k])==1: continue
    x=1
    for e in di[k]: x*=e
    ans+=x

print ans  

打印 7425

如果您想要简短的程序版本:

di={}
for t in tups:
    di.setdefault(t[0],[]).append(t[1])
print sum(reduce(lambda x,y: x*y,l) for l in di.values() if len(l)>1)

这是一个棘手的版本(来自狼):

di={}
{di.setdefault(t[0],[]).append(t[1]) for t in tups}
print sum(reduce(lambda x,y: x*y,l) for l in di.values() if len(l)>1)
于 2013-05-29T21:42:21.657 回答
0

因此,每个人都已经发布了带有内置函数的解决方案,但是编写一个循环并完成您需要的操作并不是什么额外的事情!

>>> l = [(1,4),(3,5),(2,9),(6,23),(3,21),(2,66),(5,20),(1,33),(3,55),(1,8)]
>>> hold = []
>>> for i in range(min(l)[0],max(l)[0] + 1):
...     hold2 = []
...     mult = 1
...     for t in l:
...             if t[0] == i:
...                     hold2.append(t[1])
...                     mult *= t[1]
...     if len(hold2) > 1:
...             hold.append(mult)
... 
>>> sum(hold)
7425

您设置一个数组来检查每个索引有多少,然后遍历不同的索引并继续乘以匹配索引的下一个数字!

此外,这将是您获得的最快版本。只是因为它什么都不进口,也不需要花时间去做。给你的每个版本都不到一秒,但我很无聊,所以我把它们都计时了:

Mine: 0:00:00.000477

1_CR: 00:00.073498

RedBaron: 0:00:00.079276
于 2013-05-29T17:22:03.807 回答
0

这是一个使用字典的答案:

def calculate(t):
    t1 = {}    # first time we encounter an index
    t2 = {}    # product of values
    for index, value in t:
        if index in t1:    # we have seen this index already
            if index not in t2:    # start the multiplier
                t2[index] = t1[index]
            t2[index] *= value     # chain multiplication
        else:
            t1[index] = value      # first time for this index
    return sum(t2.values())    # sum of multipliers
于 2013-05-29T22:56:43.253 回答