2

减少这一系列元组的最佳方法是什么

('x', 0.29, 'a')
('x', 0.04, 'a')
('x', 0.03, 'b')
('x', 0.02, 'b')
('x', 0.01, 'b')
('x', 0.20, 'c')
('x', 0.20, 'c')
('x', 0.10, 'c')

进入:

('x', 0.29 * 0.04 , 'a')
('x', 0.03 * 0.02 * 0.01, 'b')
('x', 0.20 * 0.20 * 0.10, 'c')

编辑: X是一个常数,它是预先知道的,可以安全地忽略

并且数据可以被视为在上面显示的第三个元素上预先排序。

我目前正在尝试使用 operator.mul 和大量模式匹配以及奇怪的 lambda 函数来实现它......但我相信一定有更简单的方法!

我可以说谢谢你所有的答案。他们每个人都很棒,而且超出了我的期望。我所能做的就是给他们一个赞成票并说声谢谢!

4

3 回答 3

6

这是一种函数式编程方法:

from itertools import imap, groupby
from operator import itemgetter, mul

def combine(a):
    for (first, last), it in groupby(a, itemgetter(0, 2)):
        yield first, reduce(mul, imap(itemgetter(1), it), 1.0), last
于 2012-06-12T21:12:41.360 回答
4

这是一种更有状态的方法。(我更喜欢@Sven。)

def combine(a)
    grouped = defaultdict(lambda: 1)

    for _, value, key in a:
        grouped[key] *= value

    for key, value in grouped.items():
        yield ('x', value, key)

如果数据已经排序,则效率会降低,因为它在内存中保留的内存比需要的多。再说一次,这可能无关紧要,因为它也不是愚蠢的低效。

于 2012-06-12T21:21:47.717 回答
3

鉴于您最终要将所有找到的值相乘,而不是累积值列表并在最后将它们相乘,请更改您的 defaultdict 以采用将新键设置为 1 的初始化方法,然后乘以您去:

data = [('x', 0.29, 'a'),
('x', 0.04, 'a'),
('x', 0.03, 'b'),
('x', 0.02, 'b'),
('x', 0.01, 'b'),
('x', 0.20, 'c'),
('x', 0.20, 'c'),
('x', 0.10, 'c'),]

from collections import defaultdict

def reduce_by_key(datalist):

    proddict = defaultdict(lambda : 1)
    for _,factor,key in datalist:
        proddict[key] *= factor

    return [('x', val, key) for key,val in sorted(proddict.items())]

print reduce_by_key(data)

给出:

[('x', 0.011599999999999999, 'a'), 
 ('x', 5.9999999999999993e-06, 'b'), 
 ('x', 0.004000000000000001, 'c')]
于 2012-06-12T21:27:38.533 回答