【Python】Python ~ 不変集合 frozenset ~

◾️はじめに

Python で辞書リストの重複を排除するために
色々調べたら、frozensetってのを使ったのでメモ。

目次

【1】frozenset
 1)仕様
【2】用途
 1)辞書のキーとして利用
【3】frozensetの利用例:辞書リストの重複排除
 1)完全一致で重複排除
 2)複数キーで重複削除

【1】frozenset

* Set の イミュータブル (変更不可能)版

=> Set に関しては、以下の関連記事を参照のこと

Python ~ 基本編 / 集合 Set ~
https://dk521123.hatenablog.com/entry/2021/04/02/000000

1)仕様

https://docs.python.org/ja/3.13/library/stdtypes.html#set-types-set-frozenset

set(集合)型 --- set, frozenset

set および frozenset という、2つの組み込みの集合型があります。
...
一方、frozenset 型はイミュータブルで、ハッシュ可能 です。
作成後に内容を改変できないため、辞書のキーや他の集合の要素として
用いることができます。
空でない set (frozenset ではない) は、...

https://docs.python.org/ja/3.13/library/stdtypes.html#frozenset

class frozenset([iterable])

iterable から要素を取り込んだ、新しい set もしくは frozenset オブジェクトを返します。
集合の要素は ハッシュ可能 なものでなくてはなりません。
集合の集合を表現するためには、内側の集合は frozenset オブジェクトでなくてはなりません。
iterable が指定されない場合、新しい空の集合が返されます。

【2】用途

1)辞書のキーとして利用

* 複数の要素をイテレータとして一意オブジェクトでまとめて
 辞書キーにする場合に使える
* 具体的な使用例は、
 後述「【3】frozensetの利用例:辞書リストの重複排除」の
 「2)複数キーで重複削除」を参照のこと

【3】frozensetの利用例:辞書リストの重複排除

* 以下の関連記事の「【7】辞書リストの重複排除」より抜粋

Python ~ 基本編 / 辞書・あれこれ ~
https://dk521123.hatenablog.com/entry/2020/10/11/000000

1)完全一致で重複排除

input_list = [
  {'id': 1, 'name': 'john', 'age': 34},
  {'id': 1, 'name': 'john', 'age': 34},
  {'id': 2, 'name': 'hanna', 'age': 30},
  {'id': 3, 'name': 'Tom', 'age': 21},
  {'id': 2, 'name': 'Kevin', 'age': 45},
]

# 完全一致で重複排除(★今回のテーマ)
results = [dict(s) for s in set(frozenset(d.items()) for d in input_list)]
print(results)
# [{'id': 2, 'age': 30, 'name': 'hanna'},
# {'age': 34, 'name': 'john', 'id': 1},
# {'name': 'Tom', 'id': 3, 'age': 21},
# {'id': 2, 'name': 'Kevin', 'age': 45}]

解説

input_list = [
  {'id': 1, 'name': 'john', 'age': 34},
  {'id': 1, 'name': 'john', 'age': 34},
  {'id': 2, 'name': 'hanna', 'age': 30},
  {'id': 3, 'name': 'Tom', 'age': 21},
  {'id': 2, 'name': 'Kevin', 'age': 45},
]

results = [frozenset(d.items()) for d in input_list]
print(results)
# [frozenset({('age', 34), ('name', 'john'), ('id', 1)}),
#  frozenset({('age', 34), ('name', 'john'), ('id', 1)}),
#  frozenset({('id', 2), ('name', 'hanna'), ('age', 30)}),
#  frozenset({('id', 3), ('age', 21), ('name', 'Tom')}),
#  frozenset({('id', 2), ('name', 'Kevin'), ('age', 45)})]

# これをSetにかけることによって重複排除している

2)複数キーで重複削除

input_list = [
  {'id': 1, 'name': 'john', 'age': 34},
  {'id': 1, 'name': 'john', 'age': 34},
  {'id': 2, 'name': 'hanna', 'age': 30},
  {'id': 3, 'name': 'Tom', 'age': 21},
  {'id': 2, 'name': 'Kevin', 'age': 45},
  {'id': 2, 'name': 'hanna', 'age': 43},
]

# [別バージョン] idとnameで重複排除
result3 = ¥
  list({frozenset([v['id'], v['name']]):v for v in input_list}.values())
print(result3)
# [{'id': 1, 'name': 'john', 'age': 34},
#  {'id': 2, 'name': 'hanna', 'age': 43},
#  {'id': 3, 'name': 'Tom', 'age': 21},
#  {'id': 2, 'name': 'Kevin', 'age': 45}]

関連記事

Python ~ 基本編 / 集合 Set ~
https://dk521123.hatenablog.com/entry/2021/04/02/000000
Python ~ 基本編 / CSV
https://dk521123.hatenablog.com/entry/2019/11/07/214108
Python ~ 基本編 / 辞書・あれこれ ~
https://dk521123.hatenablog.com/entry/2020/10/11/000000