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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Q&A

解決済

1回答

653閲覧

リスト内包表記でのgroupbyの書き方

sasaki0628

総合スコア106

Python 3.x

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

0グッド

0クリップ

投稿2023/02/05 11:37

実現したいこと

変更前データを変更後データのようにリスト形式に書き直したい

変更前データ

data =[ { "id": 1, "fruits": "apple", "cd": 1, "cd_val": "Hokkaido", }, { "id": 1, "fruits": "apple", "cd": 2, "cd_val": "Aomori" }, { "id": 1, "fruits": "apple", "cd": 4, "cd_val": "Iwate", }, { "id": 2, "fruits": "banana", "cd": 5, "cd_val": "Yamagata", }, { "id": 3, "fruits": "grape", "cd": 3, "cd_val": "Akita", }, { "id": 3, "fruits": "grape", "cd": 6, "cd_val": "Miyagi", }, { "id": 3, "fruits": "grape", "cd": 7, "cd_val": "Niigata", }, ]

変更後データ

result =[ { "id": 1, "fruits": "apple", "cd": [1,2,4], "cd_val": ["Hokkaido","Aomori","Iwate"] }, { "id": 2, "fruits": "banana", "cd": [5], "cd_val": ["Yamagata"] }, { "id": 3, "fruits": "grape", "cd": [3,6,7], "cd_val": ["Akita","Miyagi","Niigata"] } ]

試したこと

試したコード①

from pprint import pprint from itertools import groupby result = [ {'id': k[0], 'fruits': k[1], 'cd': [e['cd'] for e in group], 'cd_val': [e['cd_val'] for e in group]} for k, group in groupby(data, lambda e: (e['id'], e['fruits'])) ] pprint(result, sort_dicts=False)

コード①の出力結果

[{'id': 1, 'fruits': 'apple', 'cd': [1, 2, 4], 'cd_val': []}, {'id': 2, 'fruits': 'banana', 'cd': [5], 'cd_val': []}, {'id': 3, 'fruits': 'grape', 'cd': [3, 6, 7], 'cd_val': []}]

cd_val が 空のリストになってしまい、修正方法がわかりませんでした。

試したコード②

from pprint import pprint from itertools import groupby keyfunc = lambda x: x['id'] result = [] [result.append( {'id': k, 'fruits': list(group)[0]['fruits'], 'cd': [i['cd'] for i in list(group)], 'cd_val': [i['cd_val'] for i in list(group)]}) for k, group in groupby(sorted(data, key=keyfunc), keyfunc) ] pprint(result, sort_dicts=False)

コード②の出力結果

[{'id': 1, 'fruits': 'apple', 'cd': [], 'cd_val': []}, {'id': 2, 'fruits': 'banana', 'cd': [], 'cd_val': []}, {'id': 3, 'fruits': 'grape', 'cd': [], 'cd_val': []}]

cd と cd_val が空のリストになってしまい、修正方法がわかりませんでした。

試したコード③

from pprint import pprint from itertools import groupby keyfunc = lambda x: x['id'] result = [ {'id': k, 'fruits': list(group)[0]['fruits'], 'cd': [item['cd'] for item in list(group)], 'cd_val': [item['cd_val'] for item in list(group)]} for k, group in groupby(sorted(data, key=keyfunc), keyfunc) ] pprint(result, sort_dicts=False)

コード③の出力結果

[{'id': 1, 'fruits': 'apple', 'cd': [], 'cd_val': []}, {'id': 2, 'fruits': 'banana', 'cd': [], 'cd_val': []}, {'id': 3, 'fruits': 'grape', 'cd': [], 'cd_val': []}]

cd と cd_val が空のリストになってしまい、修正方法がわかりませんでした。

keyfunc = lambda x: x['id'] にして、リスト内包表記で書きたいと思っているのですが、コード③の修正方法がわからず、修正方法を教えていただきたいです。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

groupby() の戻り値(質問のコードの group)はイテレータなので、値を取り出すと空になってしまいます。そのため、cd_val は常に空のリストになります。なので、group をリストに変換しておきます。※ セイウチ演算子(:=)を使用しますので、実行には Python 3.8 以降が必要になります。

python

1result = [ 2 {'id': k[0], 3 'fruits': k[1], 4 'cd': [e['cd'] for e in grp], 5 'cd_val': [e['cd_val'] for e in grp]} 6 for k, group 7 in groupby(data, lambda e: (e['id'], e['fruits'])) 8 if (grp := list(group)) 9] 10 11pprint(result, sort_dicts=False) 12 13# [{'id': 1, 14# 'fruits': 'apple', 15# 'cd': [1, 2, 4], 16# 'cd_val': ['Hokkaido', 'Aomori', 'Iwate']}, 17# {'id': 2, 'fruits': 'banana', 'cd': [5], 'cd_val': ['Yamagata']}, 18# {'id': 3, 19# 'fruits': 'grape', 20# 'cd': [3, 6, 7], 21# 'cd_val': ['Akita', 'Miyagi', 'Niigata']}]

投稿2023/02/05 12:05

編集2023/02/05 12:08
melian

総合スコア19703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2023/02/05 13:21

原因はわかったのですが、内包表記の中で一時変数を作る方法がわからず回答できずにいました。 なるほど if を使えば良いのか。今回は大丈夫ですが、偽値があり得る場合は注意ですね。
sasaki0628

2023/02/05 23:03

ありがとうございます。イテレータについて不勉強でした。
bsdfan

2023/02/06 03:46

@otn 変数にセットするために、もう一回 for を回すのも使われます。これなら偽でも大丈夫。 [... for k, group in groupby(...) for grp in [list(group)]]
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問