tは最終的に使っていないようなので消したのと、不要なintを外したところだけ修正しましたが、質問文のコード
python
1r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]]
2
3d = {}
4for k,v,i in r:
5 if k in d:
6 d[k] += i
7 else:
8 d[k] = i
9
10for k,v in d.items():
11 print(k, v)
これが割とベターな気がするんですよね。シンプルでコードの姿も悪くないし。
更に単純化するとしたら、defaultdictを使ってキー有無の判定を省くことはできますが。
python
1from collections import defaultdict
2r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]]
3
4d = defaultdict(int)
5for k,v,i in r:
6 d[k] += i
7
8for k,v in d.items():
9 print(k, v)
これ以上単純化する方法は思いつきませんでした。ワンライナーで書くにしても、かえって黒魔術っぽくなっちゃうでしょう。そっちは他の方に譲ります(書く人がいれば)。
私が言いたいのは「上記コードで十分シンプルなのに、これ以上いじくり回す必要があるのか」ということです。
追記
他の方に譲る、と書いてしまったが・・・。
一行で書く別解。forをreduceで隠蔽しただけでロジックは同じ。実用上のメリットはないので、使わない方が良いです。
python
1from functools import reduce
2from collections import defaultdict
3r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]]
4result_d = reduce(lambda d, e: (d.__setitem__(e[0], d[e[0]]+e[2]), d)[1], [defaultdict(int)]+r)
怪しい_setitem_をなくしたければ辞書をループの度に作って使い捨てれば良いですが、パフォーマンス上は不利です。そしてなおさら読めない代物になる(努力と工夫とひらめき次第でもうちょっと綺麗に書ける可能性はありますが)。
python
1from functools import reduce
2r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]]
3result_d = reduce(lambda d, e: dict((k, v+e[2]) if k == e[0] else (k, v) for k, v in d.items()) if e[0] in d else {k:v for k, v in list(d.items())+[(e[0], e[2])]}, [{}]+r)
代入「文」は一行消費しちゃうので、これを使う処理は基本的に一行で綺麗には書けないことを覚えておくと良いでしょう。
2018/04/16 22:32 編集