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は定数であり、事前にわかっており、安全に無視できます

また、データは、上に表示されているように、3 番目の要素で事前に並べ替えられたものとして扱うことができます。

現在、operator.mul、多くのパターン マッチング、奇妙なラムダ関数を使用してそれを実行しようとしていますが、もっと簡単な方法があるはずです。

すべての回答に感謝します。どれも素晴らしく、期待以上でした。私にできることは、彼ら全員に賛成票を投じて感謝することだけです!

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 に答える