pattern matching, tuples and multiplication in Python

两盒软妹~` 提交于 2019-12-08 01:28:40

问题


What is be best way to reduce this series of tuples

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

into:

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

EDIT: X is a constant, it is known in advance and can be safely ignored

And the data can be treated as pre-sorted on the third element as it appears above.

I am trying to do it at the moment using operator.mul, and a lot of pattern matching, and the odd lambda function... but I'm sure there must be an easier way!

Can I just say thank you for ALL of the answers. Each one of them was fantastic, and more than I could have hoped for. All I can do is give them all an upvote and say thanks!


回答1:


Here's a more stateful approach. (I like @Sven's better.)

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)

This is less efficient if the data are already sorted, since it keeps more in memory than it needs to. Then again, that probably won't matter, because it's not stupidly inefficient either.




回答2:


Here's a functional programming approach:

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



回答3:


Given that you are ultimately going to multiply together all of the found values, instead of accumulating a list of the values and multiplying them at the end, change your defaultdict to take an initializer method that sets new keys to 1, and then multiply as you go:

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)

Gives:

[('x', 0.011599999999999999, 'a'), 
 ('x', 5.9999999999999993e-06, 'b'), 
 ('x', 0.004000000000000001, 'c')]


来源:https://stackoverflow.com/questions/11004838/pattern-matching-tuples-and-multiplication-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!