Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pattern matching, tuples and multiplication in Python

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!

like image 476
beoliver Avatar asked Aug 05 '26 21:08

beoliver


2 Answers

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
like image 54
Sven Marnach Avatar answered Aug 07 '26 13:08

Sven Marnach


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.

like image 39
Katriel Avatar answered Aug 07 '26 14:08

Katriel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!