🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

4022閲覧

辞書型のリストから差分を求めたい

hfjdsfh_48

総合スコア13

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2021/02/03 03:31

編集2021/02/03 03:51

以下の2つの辞書型のリストがあります。

python

1d1 = [{"name": "佐藤", "age": "13"},{"name": "山下", "age": "15"}] 2 3d2 = [{"name": "山崎", "age": "18"},{"name": "佐藤", "age": "13"},{"name": "山下", "age": "15"}]

この2つの辞書型リストから差分を求めたいです。つまり、

python

1{"name": "山崎", "age": "18"}

のような結果が欲しいです。
ただの辞書型の場合であればdict.keysやdict.itemsで差分を求めることはできるのですが、辞書型リストの場合、itemsがないと判断され、うまくいきません。

詳しい方、ご教授ください。

追記↓
以下のようにfor文を使って出力する事はできました。
もし他にスマートなやり方があれば教えてください。

python

1for item in d2: 2 if item in d1: 3 pass 4 5 else: 6 print(item)

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

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

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

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

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

ppaul

2021/02/03 03:38

d2に在ってd1にないものですか。 それとも、一方にだけあるものの全体ですか。
hfjdsfh_48

2021/02/03 03:41

d2にだけあるリストである{"name": "山下", "age": "15"}のみを出力したいです。 ですので、一方にだけあるものの全体ということですかね。
hfjdsfh_48

2021/02/03 03:52

追記しました。 for文を使ったら出力されそうです。 他の方法があればご指摘ください。
ppaul

2021/02/03 04:02

辞書の==はできるのですね。ならそのほうが簡単です。短く書くと、 print([x for x in d2 if not x in d1])ですね。
guest

回答3

0

nameとageでタプルにしてsetを生成し、差集合を求める。その後、辞書の形に直す。
差分が複数あることを想定すると、リストで返したほうがいいのでは。

Python

1d1 = [{"name": "佐藤", "age": "13"}, {"name": "山下", "age": "15"}] 2d2 = [{"name": "山崎", "age": "18"}, {"name": "佐藤", "age": "13"}, {"name": "山下", "age": "15"}, {"name": "本田", "age": "19"}] 3 4d1_set = set((x['name'], x['age']) for x in d1) 5d2_set = set((x['name'], x['age']) for x in d2) 6 7 8ans = [{"name": x[0], "age": x[1]} for x in d2_set - d1_set] 9print(ans)

result

1[{'name': '本田', 'age': '19'}, {'name': '山崎', 'age': '18'}]

投稿2021/02/03 04:17

編集2021/02/03 04:17
Daregada

総合スコア11990

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

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

0

今日は時間がないので、関数とか手抜きです。

python

1def eq_dict(a, b): 2 if len(a) != len(b): 3 return False 4 for k in a: 5 try: 6 if a[k] != b[k]: 7 return False 8 except Exception: 9 return False 10 return True 11 12def d_in_l(d, lists): 13 for e in lists: 14 if eq_dict(d, e): 15 return True 16 return False 17 18d1 = [{"name": "佐藤", "age": "13"},{"name": "山下", "age": "15"}] 19d2 = [{"name": "山崎", "age": "18"},{"name": "佐藤", "age": "13"},{"name": "山下", "age": "15"}] 20x = [d for d in d2 if d_in_l(d, d1) == False] 21print(x)

実行結果は以下です。

python

1>>> def eq_dict(a, b): 2... if len(a) != len(b): 3... return False 4... for k in a: 5... try: 6... if a[k] != b[k]: 7... return False 8... except Exception: 9... return False 10... return True 11... 12>>> def d_in_l(d, lists): 13... for e in lists: 14... if eq_dict(d, e): 15... return True 16... return False 17... 18>>> d1 = [{"name": "佐藤", "age": "13"},{"name": "山下", "age": "15"}] 19>>> d2 = [{"name": "山崎", "age": "18"},{"name": "佐藤", "age": "13"},{"name": "山下", "age": "15"}] 20>>> x = [d for d in d2 if d_in_l(d, d1) == False] 21>>> print(x) 22[{'name': '山崎', 'age': '18'}]

投稿2021/02/03 03:55

ppaul

総合スコア24670

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

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

0

ベストアンサー

愚直に、d2の要素をforループにかけてd1に含まれないものだけlist化しました。
一般にlistの差分はset化することで得られるようですが、中身が辞書だとうまくいかないようなので。

python3

1d1 = [{"name": "佐藤", "age": "13"},{"name": "山下", "age": "15"}] 2d2 = [{"name": "山崎", "age": "18"},{"name": "佐藤", "age": "13"},{"name": "山下", "age": "15"}] 3 4d3 = [d for d in d2 if d not in d1] 5print(d3) # -> [{'name': '山崎', 'age': '18'}]

投稿2021/02/03 03:53

編集2021/02/03 03:55
jeanbiego

総合スコア3966

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問