List 内の辞書が設定されていて、同一の内容の要素の重複を排除しようとして、
set関数を使って重複を排除しようとしたところ、
TypeError: unhashable type: 'dict'
というエラーが発生して、重複の排除ができませんでした。
これは辞書に、ハッシュ関数の実装がないために発生します。
エラーが発生するコードサンプル
key_dimensions = [{'name': 'ga:dimension8'}, {'name': 'ga:dimension10'}]
all_dimensions = [{'name': 'ga:dimension1'},
{'name': 'ga:dimension2'},
{'name': 'ga:dimension3'},
{'name': 'ga:dimension4'},
{'name': 'ga:dimension5'},
{'name': 'ga:dimension6'},
{'name': 'ga:dimension7'},
{'name': 'ga:dimension8'},
{'name': 'ga:dimension9'},
{'name': 'ga:dimension10'},
{'name': 'ga:dimension11'},
{'name': 'ga:dimension12'},
{'name': 'ga:dimension13'},
{'name': 'ga:dimension14'},
{'name': 'ga:dimension15'},
{'name': 'ga:dimension16'},
{'name': 'ga:dimension17'},
{'name': 'ga:dimension18'},
{'name': 'ga:dimension19'},
{'name': 'ga:dimension20'}]
key_dimensions.extend(all_dimensions)
key_dimensions
set(key_dimensions)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-f57935d1d554> in <module>
----> 1 set(key_dimensions)
TypeError: unhashable type: 'dict'
hashable な辞書
frozendict · PyPI を使うと、hashbaleな辞書を作ることができます。
!pip3 install frozendict
Collecting frozendict
Using cached https://files.pythonhosted.org/packages/4e/55/a12ded2c426a4d2bee73f88304c9c08ebbdbadb82569ebdd6a0c007cfd08/frozendict-1.2.tar.gz
Building wheels for collected packages: frozendict
Running setup.py bdist_wheel for frozendict ... ?[?25ldone
?[?25h Stored in directory: /Users/kensakurai/Library/Caches/pip/wheels/6c/6c/e9/534386165bd12cf1885582c75eb6d0ffcb321b65c23fe0f834
Successfully built frozendict
Installing collected packages: frozendict
Successfully installed frozendict-1.2
from frozendict import frozendict
key_dimensions = [{'name': 'ga:dimension8'}, {'name': 'ga:dimension10'}]
all_dimensions = [{'name': 'ga:dimension1'},
{'name': 'ga:dimension2'},
{'name': 'ga:dimension3'},
{'name': 'ga:dimension4'},
{'name': 'ga:dimension5'},
{'name': 'ga:dimension6'},
{'name': 'ga:dimension7'},
{'name': 'ga:dimension8'},
{'name': 'ga:dimension9'},
{'name': 'ga:dimension10'},
{'name': 'ga:dimension11'},
{'name': 'ga:dimension12'},
{'name': 'ga:dimension13'},
{'name': 'ga:dimension14'},
{'name': 'ga:dimension15'},
{'name': 'ga:dimension16'},
{'name': 'ga:dimension17'},
{'name': 'ga:dimension18'},
{'name': 'ga:dimension19'},
{'name': 'ga:dimension20'}]
key_dimensions = [frozendict(elem) for elem in key_dimensions]
all_dimensions = [frozendict(elem) for elem in all_dimensions]
key_dimensions.extend(all_dimensions)
key_dimensions
[<frozendict {'name': 'ga:dimension8'}>,
<frozendict {'name': 'ga:dimension10'}>,
<frozendict {'name': 'ga:dimension1'}>,
<frozendict {'name': 'ga:dimension2'}>,
<frozendict {'name': 'ga:dimension3'}>,
<frozendict {'name': 'ga:dimension4'}>,
<frozendict {'name': 'ga:dimension5'}>,
<frozendict {'name': 'ga:dimension6'}>,
<frozendict {'name': 'ga:dimension7'}>,
<frozendict {'name': 'ga:dimension8'}>,
<frozendict {'name': 'ga:dimension9'}>,
<frozendict {'name': 'ga:dimension10'}>,
<frozendict {'name': 'ga:dimension11'}>,
<frozendict {'name': 'ga:dimension12'}>,
<frozendict {'name': 'ga:dimension13'}>,
<frozendict {'name': 'ga:dimension14'}>,
<frozendict {'name': 'ga:dimension15'}>,
<frozendict {'name': 'ga:dimension16'}>,
<frozendict {'name': 'ga:dimension17'}>,
<frozendict {'name': 'ga:dimension18'}>,
<frozendict {'name': 'ga:dimension19'}>,
<frozendict {'name': 'ga:dimension20'}>]
set(key_dimensions)
{<frozendict {'name': 'ga:dimension1'}>,
<frozendict {'name': 'ga:dimension10'}>,
<frozendict {'name': 'ga:dimension11'}>,
<frozendict {'name': 'ga:dimension12'}>,
<frozendict {'name': 'ga:dimension13'}>,
<frozendict {'name': 'ga:dimension14'}>,
<frozendict {'name': 'ga:dimension15'}>,
<frozendict {'name': 'ga:dimension16'}>,
<frozendict {'name': 'ga:dimension17'}>,
<frozendict {'name': 'ga:dimension18'}>,
<frozendict {'name': 'ga:dimension19'}>,
<frozendict {'name': 'ga:dimension2'}>,
<frozendict {'name': 'ga:dimension20'}>,
<frozendict {'name': 'ga:dimension3'}>,
<frozendict {'name': 'ga:dimension4'}>,
<frozendict {'name': 'ga:dimension5'}>,
<frozendict {'name': 'ga:dimension6'}>,
<frozendict {'name': 'ga:dimension7'}>,
<frozendict {'name': 'ga:dimension8'}>,
<frozendict {'name': 'ga:dimension9'}>}
# _dict で辞書が取得できます
key_dimensions[0]._dict
{'name': 'ga:dimension8'}
# _hashでhash値が取得できます
key_dimensions[0]._hash
-5282691924994355217
# get(key名)でVlaue値が取得できます。
key_dimensions[0].get("name")
'ga:dimension8'
List内包表記で重複を排除する
frozendict
は 辞書 ではないので、辞書を引数にとるメソッド呼び出し前のデータ加工時は特に役に立たないかもしれません。
Stack Overflow の記事に List 内包表記で重複を排除するサンプルが記載されていて、それが個人的にいい感じに思いましたので、記載します。
key_dimensions = [{'name': 'ga:dimension8'}, {'name': 'ga:dimension10'}]
all_dimensions = [{'name': 'ga:dimension1'},
{'name': 'ga:dimension2'},
{'name': 'ga:dimension3'},
{'name': 'ga:dimension4'},
{'name': 'ga:dimension5'},
{'name': 'ga:dimension6'},
{'name': 'ga:dimension7'},
{'name': 'ga:dimension8'},
{'name': 'ga:dimension9'},
{'name': 'ga:dimension10'},
{'name': 'ga:dimension11'},
{'name': 'ga:dimension12'},
{'name': 'ga:dimension13'},
{'name': 'ga:dimension14'},
{'name': 'ga:dimension15'},
{'name': 'ga:dimension16'},
{'name': 'ga:dimension17'},
{'name': 'ga:dimension18'},
{'name': 'ga:dimension19'},
{'name': 'ga:dimension20'}]
key_dimensions.extend(all_dimensions)
[dict(s) for s in set(frozenset(d.items()) for d in key_dimensions)]
[{'name': 'ga:dimension6'},
{'name': 'ga:dimension8'},
{'name': 'ga:dimension20'},
{'name': 'ga:dimension9'},
{'name': 'ga:dimension11'},
{'name': 'ga:dimension13'},
{'name': 'ga:dimension12'},
{'name': 'ga:dimension18'},
{'name': 'ga:dimension16'},
{'name': 'ga:dimension1'},
{'name': 'ga:dimension19'},
{'name': 'ga:dimension17'},
{'name': 'ga:dimension15'},
{'name': 'ga:dimension10'},
{'name': 'ga:dimension4'},
{'name': 'ga:dimension14'},
{'name': 'ga:dimension2'},
{'name': 'ga:dimension5'},
{'name': 'ga:dimension3'},
{'name': 'ga:dimension7'}]
参考
以上です。
コメント