setの機能:重複削除
以前setの利点として
setを使う理由の1つは要素の重複を無くす事
と書いた。
確かにiterableなデータを扱うにあたってのsetの良さの一つ。
公式チュートリアルの 5. Data Structuresの5.4. Setsにも下記の通り記載されている様に、メンバーシップに漏れやダブりがないかのテストや、ダブりの発見、削除に使える。
Python also includes a data type for sets. A setis an unordered collection with no duplicate elements. Basic uses include membership testing and eliminating duplicate entries.
setの機能:集合論(Set theory)
しかしsetの機能はそれだけではなく、listやdictやtupleには無い、便利に使える機能がある、と説明は続く。
それは数学の集合論(Set theory)に関する機能。
Set objects also support mathematical operations like union, intersection, difference, and symmetric difference.
そんな機能の備忘録。
これは公式チュートリアル、Built-in Typesのclass set/class frozenesetとPEP 218 – Adding a Built-In Set Object Typeを参考にしています。
以下のa, b2つのset型データを用意。
a、bどちらもsetを作るコード。
>>> a = set(["red", "blue", "yellow", "red", "yellow", "blue", "blue"]) >>> b = {"green", "red", "orange", "white", "green", "orange"} >>> a {'red', 'yellow', 'blue'} >>> b {'green', 'red', 'white', 'orange'}
和集合(Union):論理和(OR)
和集合(Union)とは、二つのsetの要素を合わせた全てのset(重複の無い要素)。
論理演算の用語では論理和(OR)。
これを得るには、
(片方のset).union(もう一方のset)
演算子(operator)を使う場合は、
“片方のset | もう一方のset” で。
>>> a.union(b) {'red', 'white', 'orange', 'blue', 'green', 'yellow'} >>> a | b {'red', 'white', 'orange', 'blue', 'green', 'yellow'}
a、b両方に含まれる全ての要素を返している。
積集合、共通部分、交差(intersection):論理積(AND)
積集合、共通部分、交差(intersection)とは、二つのsetに共通してある要素。
論理演算の用語では論理積(AND)。
これを得るには、
(片方のset).intersection(もう一方のset)
演算子(operator)を使う場合は
“片方のset & もう一方のset” で。
>>> a.intersection(b) {'red'} >>> a & b {'red'}
今回はaとbのintersectionは”red”のみ。
差集合(difference):一方から見た否定(NOT)
差集合(difference)は、片方のsetから見て相手が持っていない要素を返す。
論理演算の用語ではその片方のsetから見た否定(NOT)。
これを得るには、
(片方のset).difference(もう一方のset)
演算子(operator)を使う場合は、
“片方のset – もう一方のset” で。
「片方のsetから見て相手が持っていないもの」なので、自分がどちらかによって返ってくるものが変わってくる。
>>> a.difference(b) {'blue', 'yellow'} >>> a - b {'blue', 'yellow'} >>> b.difference(a) {'green', 'white', 'orange'} >>> b - a {'green', 'white', 'orange'}
aは{‘red’, ‘yellow’, ‘blue’}、
bは{‘green’, ‘red’, ‘white’, ‘orange’}なので、
aから見た相手(b)が持たないものは’red’以外の’blue’, ‘yellow’であり、
bから見た相手(a)が持たないものは’red’以外の’green’, ‘white’, ‘orange’である。
対称差集合(Symmetric Difference Set):排他的論理和(EOR, XOR)
対称差集合(Symmetric Difference
Set)とは、双方のsetの要素の内、双方に含れれない片側だけに含まれた要素で作られた新しいsetを返す。
論理演算の用語では排他的論理和(EOR, XOR)
これを得るには、
(片方のset).symmetric_difference(もう一方のset)
演算子(operator)を使う場合は、
“片方のset ^ もう一方のset” で。
>>> a.symmetric_difference(b) {'green', 'white', 'orange', 'blue', 'yellow'} >>> a ^ b {'green', 'white', 'orange', 'blue', 'yellow'}
双方のsetに含まれる”red”以外の全ての要素を含むsetが返されている。
共通の要素が有るか無いか
双方のsetに共通要素があるかチェックするには”isdisjoint()”を使用する。
共通要素が有ればFalse、共通要素が無ければTrueを返す。
>>> c = {'black', 'gray'} >>> a.isdisjoint(c) True >>> a.isdisjoint(b) False
cの’black’、’gray’について、aにはどちらも含まれていないので、Trueが返ってくる。bには’black’が含まれているのでFalseが返ってくる。
そのsetはもう一つの集合の部分集合か?:subset
一般論
そのsetに含まれる要素が、他方のsetに全て含まれていればTrue、含まれていないものがあればFauseを返す。
これを得るには、
(片方のset).issubset(もう一方のset)
(片方のset).issuperset(もう一方のset)
演算子(operator)を使う場合は、
“片方のset < もう一方のset” または、
“片方のset <= もう一方のset”で。
bの要素’white’、’red’を含むset dと、bと要素が全く同じeを用意。
>>> d = {'white', 'red'} >>> e = {'red', 'white', 'orange', 'green'} # 異なる要素を含む場合 >>> d.issubset(a) False # dはaに含まれていない要素を含む >>> d < a False # 同上 # 部分集合の場合(operator不使用) >>> d.issubset(b) True # dの要素はbに含まれているのでTrue >>> d.issuperset(b) False # dの要素がbに全て含まれていないのでFalse >>> e.issubset(b) True # eの要素はbに含まれているのでTrue >>> e.issuperset(b) True # eの要素がbに全て含まれているのでTrue # 部分集合の場合(operator使用) >>> d < b True # dの要素はbに含まれているのでTrue >>> d <= b True # dとbは同じでは無いものの、dの要素はbに含まれているのでTrue >>> e < b False # eの要素はbに含まれていて、かつ全ての要素が同じ(イコール)で "<" では無いからFalse >>> e <= b True # eの要素はbに含まれていて、かつ全ての要素が同じなのでTrue
注意:微妙にずれている範囲
注意しておきたいのは、issubset()、issuperset()と”<(>)” , “<=(>=)” の場合微妙に判定がずれる事。
issubset()は(片方のset) <= (他方のset)だけで双方が同一かは問わずTrueを返し、
issuperset()は (片方のset) <= (他方のset)でかつ、双方が同一ならTrueとする。
<(と>)は(片方のset) < (他方のset)を問い、同一の場合はFalseとし、
<= (と>=)はただ(片方のset) <= (他方のset)を問い双方が同一でなくてもTrueを返す。
issuperset()は一番厳しい判断をし、<=(と>=)は一番緩い判断、と言う理解。
注意:演算子(operator)を使う場合は注意
Built-in Typesのclass set/class frozenesetには下記説明がある。
Note, the non-operator versions of union()
, intersection()
, difference()
, symmetric_difference()
, issubset()
, and issuperset()
methods will accept any iterable as an argument. In contrast, their operator based counterparts require their arguments to be sets. This precludes error-prone constructions like set('abc') & 'cbs'
in favor of the more readable set('abc').intersection('cbs')
.
(意訳)演算子(operator)を使わずに、union(), intersection(), difference(), symmetric_difference(), issubset(), issuperset() メソッドを使う分には細かい事を気にせず様々なiterableを使用できるが、operatorでメソッドを使う分には、引数は集合であることが必要にる。よって、例えばset(‘abc’) & ‘cbs’のようなエラーを起こしやすいコードは避けて、より読みやすい set(‘abc’).intersection(‘cbs’)と書くなど、operatorでは無いメソッドを使用する方が好ましい。
部分集合の判断の所で”<“と”>”についてはoperatorしか無いように思われるが、それ以外でoperatorを使う必要がある場合については、エラーの可能性がないか注意しながら使いたい。
コメント