[解決!Python]内包表記で集合を作成するには解決!Python

集合内包表記を使って集合を作成する方法と、set関数との差、if句との組み合わせ、注意点などを紹介する。

» 2021年07月20日 05時00分 公開
[かわさきしんじDeep Insider編集部]
「解決!Python」のインデックス

連載目次

# 集合内包表記の基本型
squared = {n ** 2 for n in range(10)}
print(squared)  # {0, 1, 64, 4, 36, 9, 16, 49, 81, 25}など

# 集合なので同じ値の要素が重複することはない
mystr = 'abccba'
diff = ord('a') - ord('A'# 32
myset = {chr(ord(c) - diff) for c in mystr}
print(myset)  # {'A', 'C', 'B'}など

# 単に重複する要素を削除したいのであればset関数を使う
mystr = 'abccba'
myset = {c for c in mystr}
print(myset)  # {'a', 'b', 'c'}など

myset = set(mystr)
print(myset)  # {'a', 'b', 'c'}など

# if句と組み合わせる
mylist = [7, 4, 4, 7, 5, 9, 8, 5, 1, 10]
myset = {n for n in mylist if n % 2 == 0# mylistから偶数のみの集合を作成
print(myset)  # {8, 10, 4}など


集合内包表記の基本型

 内包表記は集合の作成にも使える。以下にその基本構文を示す。

s = {要素の値を計算する式 for 値の計算で使用する変数 in 反復可能オブジェクト}


 集合内包表記では、リストとは異なり(また、辞書とは同様に)、外側を波かっこ「{}」で囲む。このとき、辞書内包表記ではキーと値を計算する式を記述するが、集合内包表記では集合に含まれる要素の値を計算する式だけを記述すればよい。

 以下に簡単な例を示す。

squared = {n ** 2 for n in range(10)}
print(squared)  # {0, 1, 64, 4, 36, 9, 16, 49, 81, 25}など


 この例では、0〜9の整数値を二乗した値を要素とする集合を作成している。なお、要素の表示順は上の出力結果とは異なるかもしれない。

 集合内包表記が作成するのは集合なので、ある集合の中に重複する要素は含まれない。以下はその例だ。

mystr = 'abccba'
diff = ord('a') - ord('A'# 32
myset = {chr(ord(c) - diff) for c in mystr}
print(myset)  # {'A', 'C', 'B'}など

mylist = [chr(ord(c) - diff) for c in mystr]
print(mylist)  # ['A', 'B', 'C', 'C', 'B', 'A']:リストでは要素の重複が許される


 この例では、'abccba'という文字列(反復可能オブジェクト)を基に、各文字を大文字化したものを要素とする集合(とリスト)を作成している。同じ要素を重複して集合に含めることはできないので、集合では'a'、'b'、'c'が1つずつ格納されている。同一要素の重複が許されるリストには、それらが2つずつ格納されている点に注目しよう。

 なお、何らかの反復可能オブジェクトから重複する要素を削除したいだけであれば、内包表記を使わずに以下のようにset関数に渡すだけで、そうした集合が得られることは覚えておこう。

mystr = 'abccba'
myset = {c for c in mystr}
print(myset)  # {'a', 'b', 'c'}など


 集合内包表記は、反復可能オブジェクトの値を何らかの形で加工やフィルタリングした結果を要素とする集合を得るのに使用するということだ。

 リストや辞書の内包表記と同様にif句や条件式(三項演算子)も使用できる。以下に簡単な例を示す。

mylist = [7, 4, 4, 7, 5, 9, 8, 5, 1, 10]
myset = {n for n in mylist if n % 2 == 0# mylistから偶数のみの集合を作成
print(myset)  # {8, 10, 4}


 ここでは集合の要素が偶数だけとなるようにif句でフィルタリングをしている。

注意点

 辞書のキーと同様に、集合の要素にできるのはハッシュ可能なオブジェクトのみである点には注意。リストや辞書など、その内容が変更可能なオブジェクト(ハッシュ不可能なオブジェクト)を集合の要素にはできない。

klist = [[1, 2], [3, 4]]
vlist = ['foo', 'bar']

s = {(k, v) for k, v in zip(klist, vlist)}  # TypeError: unhashable type: 'list'


 この例では、リストを要素とするリストと文字列リストをzip関数で組み合わせて、「リストと文字列を要素とするタプル」を含んだ集合を作ろうとしているが、リストはハッシュ不可能であるため、TypeError例外が発生する。

 タプルのようにイミュータブル(変更不可能)なオブジェクトであっても、その要素がリストや辞書のように変更可能なオブジェクトであれば、それらを集合の要素とすることはやはりできない。

「解決!Python」のインデックス

解決!Python

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。