質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.87%

  • Python 3.x

    4800questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

特定の数字を含む時の集計

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 110

Sample_Test

score 122

一番左側の数字が含む時に右側の数字を数字を集計したい。
取り敢えず、setで重複をなくして、inで確認を取りましたが、
ココから、どの様にすれば良いですか?

appendで別の配列に入れても、合計しか出ません。

望む出力結果

[[3,330],[4,95]]

現状のコード

r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]] 

t=[i[0] for i in r]
t=list(set(t))

for i in t:
    for n in r:
#        print(i,n)
        if i in n:
            print(i,n[2])
"""
3 70
3 170
3 90
4 55
4 40
"""

過去の質問を参考にしましたが、引数が助長的になってしまいます。
改善する方法は有りますか?

コード

r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]] 

t=[i[0] for i in r]
t=list(set(t))

d = {}
for k,v,i in r:
    if k in d:
        d[k] += int(i)
    else:
        d[k] = int(i)

for k,v in d.items():
    print(k, v)

"""
3 330
4 95

"""

for文内のk,v,iなど省略したりできませんか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+3

numpyのarrayに変換したほうが操作が簡単です。以下にtを作った後のコードを示します

import numpy
result=[]
arr=numpy.array(r)
for i in t:
    tmp=numpy.sum(arr[arr[0]==i,2])
    result.append([i,tmp])

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/17 06:49 編集

    numpyは使った事が無いので見送りました。
    ありがとう、です。

    キャンセル

checkベストアンサー

+2

tは最終的に使っていないようなので消したのと、不要なintを外したところだけ修正しましたが、質問文のコード

r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]] 

d = {}
for k,v,i in r:
    if k in d:
        d[k] += i
    else:
        d[k] = i

for k,v in d.items():
    print(k, v)


これが割とベターな気がするんですよね。シンプルでコードの姿も悪くないし。
更に単純化するとしたら、defaultdictを使ってキー有無の判定を省くことはできますが。

from collections import defaultdict
r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]] 

d = defaultdict(int)
for k,v,i in r:
    d[k] += i

for k,v in d.items():
    print(k, v)


これ以上単純化する方法は思いつきませんでした。ワンライナーで書くにしても、かえって黒魔術っぽくなっちゃうでしょう。そっちは他の方に譲ります(書く人がいれば)。
私が言いたいのは「上記コードで十分シンプルなのに、これ以上いじくり回す必要があるのか」ということです。

 追記

他の方に譲る、と書いてしまったが・・・。
一行で書く別解。forをreduceで隠蔽しただけでロジックは同じ。実用上のメリットはないので、使わない方が良いです。

from functools import reduce
from collections import defaultdict
r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]] 
result_d = reduce(lambda d, e: (d.__setitem__(e[0], d[e[0]]+e[2]), d)[1], [defaultdict(int)]+r)


怪しい_setitem_をなくしたければ辞書をループの度に作って使い捨てれば良いですが、パフォーマンス上は不利です。そしてなおさら読めない代物になる(努力と工夫とひらめき次第でもうちょっと綺麗に書ける可能性はありますが)。

from functools import reduce
r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]] 
result_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)


代入「文」は一行消費しちゃうので、これを使う処理は基本的に一行で綺麗には書けないことを覚えておくと良いでしょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

from itertools import groupby
from operator import itemgetter

r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]]

d = []
for (k, g) in groupby(r, key=itemgetter(0)):
    items = [v for v in g]
    d.append([k, sum(item[2] for item in items)])

print(d)


実行結果
イメージ説明

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/17 07:36

    値が増えても対応できそうですね。

    キャンセル

+1

1行で。
ほぼ、katoyさん。
インデックスが連続していないとソートしておく必要が。

r=[[3, 20, 70], [3, 40, 170], [3, 59, 90], [4, 5, 55], [4, 25, 40]] 

from itertools import groupby

f = lambda r: {k:sum(x[-1] for x in v) for k, v in groupby(sorted(r, key=lambda x: x[0]), key=lambda x: x[0])}

a = f(r)
print(a)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/17 07:46 編集

    思ったより長くなるんですね。
    ありがとうございます。

    キャンセル

  • 2018/04/17 08:08

    一般的にはソートの前処理が必要であることと、sortedとgroupbyのキーにlambda式を使っているせいですね。
    _x0 = lambda x: x[0]
    を先に作って使い回せば少し短くなります。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.87%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    4800questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。