问题
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