🍣

Pythonの、辞書型のリストの要素をユニークにする

2020/11/10に公開
2

タイトルの通りのことをしたかったのですが、ググっても少し高度なことをやっている記事しか見かけなかったため、少し無理やりではありますが

  1. 辞書型を文字列に変換
  2. 文字列をハッシュ値に変換
  3. ハッシュ値をキーとして辞書型をバリューに入れる

という方法により、実現しました。

実装

import hashlib

hash_dicts = {}

for hoge_dict in hoge_dicts:
    dict_str = str(hoge_dict)
    hs = hashlib.sha256(str(dict_str).encode()).hexdigest()
    hash_dicts[hs] = hoge_dict

# これが得たいリスト
hoge_dicts = list(hash_dicts.values())

注意点

コメントでいただきました通り、
上記実装では文字列にする際に辞書型のキーや、バリューがリストの場合の順序を考慮しないため実態としては同じものなのに別と認識されることがあります。

このため、自前で辞書型を定義していてキーの順序などは守られている場合などにはそのまま使っていただいて構いませんが、その限りではない場合には適宜defaultdictに変換する処理を挟むなどをしていただければと思います。

Discussion

Kasai MitsuruKasai Mitsuru

Pythonのdictはキーの順序を管理しないことに注意してください。
文字列に変換したときに、どのキーから順番に出力されるかは不定(実装によって変わる可能性がある)です。

例えば、手元のCPythonでは下記のような挙動をしています。

d1 = {'a': True, 'b': True}
d2 = {'b': True, 'a': True}
print(str(d1))  # "{'a': True, 'b': True}"
print(str(d2))  # "{'b': True, 'a': True}"
print(hash(str(d1)) == hash(str(d2)))  # False

@yasudeさんのアルゴリズムではd1d2が同じ辞書と判定されませんが、恐らく意図通りではないと思いますので気をつけてください。

yasudeyasude

gen bi様

コメントありがとうございます。
いただいた内容を反映して修正いたしました。