2013-05-29 26 views
1

我有一个元组列表如下如何在python中以棘手的方式执行以下操作?

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

现在我需要像这样

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

如果有人能帮助我,我会非常感激。我是Python新手,所以很难找到它。

回答

1

将所有元组转换为字典,其中键是第一个元素,值是第二个元素的列表。筛选具有多个元素的值的字典。使用reduce()将每个值的元素相乘,然后sum()将所有产品一起添加。

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 
+0

显示中间结果已经教育价值。 ;) –

+1

@MikeMüller,好点:-)。但是,中间打印会过早耗尽此解决方案所基于的生成器表达式。 – iruvar

+0

当然。从“groupby”开始,您需要在打印后再次执行所有步骤。 –

0

另一个(slighlty不同)的方式。我们收集的元素融入一本字典,其中每个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 
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 
0

上面的答案是伟大的,但不容易理解。不幸的是,打印z之一作为groupby之后开始的可读列表将消耗1_CR指出的迭代器。这里是解决方案,但打印出中间步骤。从逻辑上说,从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 
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) 

这里是一个棘手版本(来自th Ë狼):

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) 
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 
相关问题