配列の重複した内容を削除する方法!!

takkun
どうも!たっくんです。
明日から3連休!皆さんはゆっくり休めそうですか?

Pythonでlist型やtuple型などを扱っていると、時々重複した内容を削除したい時ありませんか!?そんな時に役立つ「set型」をご紹介したいと思います!(`・ω・´)ゞ

Set型って?

Set型は、集合を表すデータ型です。っと言われても「はぁ?」って感じですよね(;´∀`)

List型、tuple型と同様に複数の要素をもつことができますが、「要素の順番を持たない」「重複した要素を入れることができない」という点が大きく違います。

Set型は直接データを作ることができず、list型、tuple型、dict型から変換して作ります。

set([0, 0, 1, 1])
# set([0, 1])

set((0, 0, 1, 1))
# set([0, 1])

set({'A':0, 'A':1, 'B':0, 'B':1})
# set(['A', 'B']) 

Dict型からの場合は、DictのKeyがSet型の要素になります。用途はないかも、、、(;´∀`)

で!

list型から重複した内容を取り除きたい場合は、以下のようにset型に変換してからlist型にもどしてあげるとOKです(`・ω・´)ゞ

listData = [0, 0, 1, 1]
print list(set(listData))
# [0, 1]

重複した0と1が取り除かれて、2つの要素になりました!

しかし!

多次元配列(Listの中にListを入れた場合など)は、上記のようには行きません。。。。(´・ω・`)

listData = [[0, 1, 0], [0, 1, 0], [0, 0, 1], [0, 0, 1]]
print list(set(listData))
# Error: TypeError: line 2: unhashable type: 'list' # 

3Dの場合は、法線が一致していたら、、、座標が一致していたら、、、などと複数の要素である場合が多いですよね、、、

これは、 リストがhashableでない ことが原因です。Pythonのヘルプにも、set型の要素はhashable (ハッシュ可能な) オブジェクトである必要があると書かれています。

hashableとは、以下の条件を満たすものの事をいいます(`・ω・´)ゞ

  • 他のオブジェクトと比較できる
  • データの変更が不可能

List型は要素の中身を書き換えられてしまうので、ダメってことですね、、、(´;ω;`)

こんな時は、多次元配列の中身をtuple型などに変更するとうまくいきます!

listData = [(0, 1, 0), (0, 1, 0), (0, 0, 1), (0, 0, 1)]
print list(set(listData))
# [(0, 1, 0), (0, 0, 1)]

先日公開した「Recovery Edge Type」でも、法線の重複を見つけるのにsetを使ってやっています(`・ω・´)ゞ

他にも「集合演算」なるものがあり、「setAの要素からsetBに含まれる要素を削除」「setAかsetBに含まれる要素の抽出」などなど色々できてすっごく便利です!

もしfor分でこねくり回して要素の査定をしている場合、set型を使うと簡単に済むかもしれません!

是非みなさんも、set型使ってみてください!(`・ω・´)ゞ