[Python] set型による集合演算の基本

Python 組込み型

set型は、集合を扱うデータ型です。順序が無くデータの重複も無いことが特徴です。これを利用してリスト型データから重複を取り除く操作にも使われます。また、他のset型データとの和集合、差集合等の数学的な集合演算もできます。他にも可変(ミュータブル)であったり、イテラブルであるといった特徴を持っています。今回はこのようなset型の基本についてまとめます。
# 2019/02/21 記事更新

確認した環境

  • OS: Ubuntu 16.04LTS
  • Python: ver3.7.0

set型の作り方

2つあります。

(1)要素をカンマで区切って”{ }”で囲う

#{}で囲います
>>> s = {'one', 'two', 'three'}

#データ型を確認
>>> type(s)
<class 'set'>

(2)setコンストラクタを生成

class set([iterable])
class frozenset([iterable])

引数iterableから新しいset(またはfrozenset)オブジェクトを生成します。iterableが空の場合は空の集合が返ります。

#リストを例にします
>>> a = ['one', 'two', 'three']

#setオブジェクトの生成
>>> a_ = set(a)
>>> a_
{'one', 'two', 'three'}

#データ型を確認
>>> type(a_)
<class 'set'>

#frozensetオブジェクトの生成
>>> f_ = frozenset(a)
>>> f_
frozenset({'one', 'two', 'three'})

#データ型を確認
>>> type(f_)
<class 'frozenset'>

set型の特徴

  1. 順序がない
  2. 可変(ミュータブル)
  3. 重複がない
  4. イテラブルなコンテナオブジェクト
  5. 集合演算が可能

以下、それぞれの特徴について詳細を示します。

(1)順序がない

setオブジェクトは、順序がありません。よって、リストや文字列で使われるインデックス指定やスライス操作等のシーケンス的な操作はできません

#以下の集合a_を例にします
>>> a_
{'one', 'two', 'three'}

#インデックス指定はできません。
>>> a_[0]
Traceback (most recent call last):
File "", line 1, in 
TypeError: 'set' object does not support indexing

(2)可変(ミュータブル)

set型は(可変)ミュータブルなオブジェクトです。ミュータブルなため、

  • ハッシュ値を持たず、辞書のキーや他の集合の要素として用いることができません
  • 後からadd()やremove()メソッドで更新が可能です。

それぞれの例を以下に示します。

要素追加する:add(elem)

引数elemは追加したい要素を示します。

>>> a_ = {'one', 'two', 'three'}

>>> a_.add('four')
>>> a_
{'one', 'two', 'four', 'three'}

要素を削除する:remove(elem)

引数elemは削除したい要素を示します。

>>> a_ = {'one', 'two', 'three'}
>>> a_.remove('one')
>>> a_
{'two', 'three'}

#elem が set に含まれていなければ KeyError を送出
>>> a_.remove('one')
Traceback (most recent call last):
File "", line 1, in 
KeyError: 'one'

要素を削除する:discard(elem)

removeメソッドとの違いは、elemがsetに含まれていない場合にNone返します。

>>> a_ = {'one', 'two', 'three'}

>>> a_.discard('one')
>>> a_
{'two', 'three'}

#elem が set に含まれていなければNoneを返します
>>> a_.discard('one')
>>> print(a_.discard('one'))
None

任意の要素を取り除く:pop()

setから任意の要素を取り除き、それを返します。集合が空の場合、KeyError を送出します

>>> a_ = {'one', 'two', 'three'}

>>> a_.pop()
'one'
>>> a_.pop()
'two'
>>> a_.pop()
'three'

#集合が空の場合エラーを送出
>>> a_.pop()
Traceback (most recent call last):
File "", line 1, in 
KeyError: 'pop from an empty set'

#ちなみに引数は取りません
>>> a_
{'one', 'two', 'three'}
>>> a_.pop(1)
Traceback (most recent call last):
File "", line 1, in 
TypeError: pop() takes no arguments (1 given)

全ての要素を削除する:clear()

>>> a_ = {'one', 'two', 'three'}
>>> a_.clear()
>>> a_
set()

尚、同じ集合型でfrozenset型は不変でハッシュ可能(hashable)なので、別の集合型の要素になったり、辞書のキーにすることができます。
frozensetオブジェクトは上記のaddやremoveなどで更新ができません。

>>> f_
frozenset({'one', 'two', 'three'})

#frozensetオブジェクトはaddやremoveで更新ができません
>>> f_.add('four')
Traceback (most recent call last):
File "", line 1, in 
AttributeError: 'frozenset' object has no attribute 'add'

>>> f_.remove('one')
Traceback (most recent call last):
File "", line 1, in 
AttributeError: 'frozenset' object has no attribute 'remove'

(3)重複がない

例えばリストから重複した要素を取り除くのに使えます。

>>> l = ['one', 'two', 'three', 'one', 'two', 'three']
>>> set(l)
{'one', 'two', 'three'}

リストに変換すれば、重複を省いたリストが生成できます。

>>> list(set(l))
['one', 'two', 'three']

(4)イテラブルである

他のコンテナオブジェクト同様に、 x in set, len(set), for x in set が使えます。

  • setオブジェクトの場合
>>> a_ = {'one', 'two', 'three'}

>>> 'one' in a_
True

>>> len(a_)
3

>>> for x in a_:
... print(x)
... 
one
two
three
  • frozensetオブジェクトの場合
>>> f_
frozenset({'one', 'two', 'three'})

>>> 'one' in f_
True

>>> len(f_)
3

>>> for x in f_:
... print(x)
... 
one
two
three

参考として、(3),(4)で挙げた性質を利用して、リストの要素が全部同じかどうかを調べることができます。つまり、重複を除いて出来た集合の長さが1の場合は、要素が全て同じ、2以上なら異なる要素が含まれている。

#リストの要素が異なる値の場合、長さが2以上
>>> a = [1, 1, 2, 1]
>>> len(set(a))
2

#リストの要素が全部同じ場合、長さが1
>>> b = [1, 1, 1, 1]
>>> len(set(b))
1

(5)集合演算が可能

共通集合、和集合、差、対象差集合のような数学的な演算が可能です。

和集合:A∪B

<書式>

A.union(*B) または A | B | ...

<例>

>>> A = {1, 2, 3, 4}
>>> B = {3, 4, 5, 6}

#和集合
>>> A.union(B)
{1, 2, 3, 4, 5, 6}

#または、

>>> A | B
{1, 2, 3, 4, 5, 6}

共通(積)集合:A∩B

<書式>

A.intersection(*B) または A & B & ...

<例>

>>> A = {1, 2, 3, 4}
>>> B = {3, 4, 5, 6}

#共通(積)集合
>>> A.intersection(B)
{3, 4}

#または

>>> A & B
{3, 4}

差集合:A-B

<書式>

A.difference(*B) または A - B - ...

<例>

>>> A = {1, 2, 3, 4}
>>> B = {3, 4, 5, 6}

#差集合
>>> A.difference(B)
{1, 2}

#または
>>> A - B
{1, 2}

対象差集合:A △ B

“A に属し、B に属さないもの” と “B に属し、A に属さないもの” とを全部集めて得られる集合

A.symmetric_difference(B) または A ^ B

<例>

>>> A = {1, 2, 3, 4}
>>> B = {3, 4, 5, 6}

#対象差集合
>>> A.symmetric_difference(B)
{1, 2, 5, 6}

#または
>>> A ^ B
{1, 2, 5, 6}

まとめ

set型は集合を表すデータ型であり、以下の特徴を持っている。

  • 順序がない・・・リスト型とは異なりスライス操作が出来ないことに注意
  • 可変(ミュータブル)・・・add()やremove()でデータの更新が可能
  • 重複がない・・・データから重複を除くのに使える
  • イテラブルなコンテナオブジェクト・・・forループで使える
  • 集合演算が可能・・・和集合、差集合等の数学的集合演算が可能

<参考記事>

Learn more...

書籍でもう少し詳しく学びたい場合はこちらもどうぞ。筆者もかなり参考にさせてもらっています!

シェアする
ひびきをフォローする
Hbk project

コメント

  1. […] 参考記事:[Python] set型による集合演算の基本 […]

  2. […] 参考記事:[Python] set型による集合演算の基本 […]