【Python】setにおけるorder(順序)
目次
Pythonのsetに順序はあるのか?
Pythonの組み込み型set
は、数学的な集合を扱うデータ型であり、要素の順序を保持しません。
つまり、挿入した順序や特定の規則に基づく並び順を保証しないため、次のような挙動になります。
my_set = {3, 1, 4, 1, 5, 9, 2, 6}
print(my_set) # 出力結果はランダム(バージョンによる)
Python 3.6以降、CPythonの実装ではset
の内部順序が挿入順に見えることがありますが、これは仕様ではなく保証されていません。
setの基本的な振る舞い
setは内部的にハッシュテーブルを用いて要素を管理しており、次のような特徴があります。
- 重複を許さない
- 順序を保持しない
- 検索・追加・削除が平均O(1)で高速
例えば、以下のコードを実行すると順序が保証されないことがわかります。
sample_set = {10, 20, 30, 40, 50}
print(sample_set) # 出力順序は一定ではない
順序を保持するデータ型
順序を保持しながら集合を扱いたい場合、いくつかの方法が考えられます。
list
を用いるdict
(Python 3.7以降で順序保証)collections.OrderedDict
OrderedSet
(外部ライブラリ使用)
例えば、リストを用いて重複を排除しつつ順序を保持するには以下のようにします。
def unique_ordered_list(iterable):
seen = set()
return [x for x in iterable if not (x in seen or seen.add(x))]
data = [3, 1, 4, 1, 5, 9, 2, 6]
print(unique_ordered_list(data)) # [3, 1, 4, 5, 9, 2, 6]
setの要素を順序付ける方法
set自体には順序がないため、要素を昇順や降順で取得するにはsorted()
を用います。
numbers = {4, 2, 9, 1, 5}
sorted_numbers = sorted(numbers) # [1, 2, 4, 5, 9]
print(sorted_numbers)
また、降順に並べる場合はreverse=True
を指定します。
sorted_desc = sorted(numbers, reverse=True) # [9, 5, 4, 2, 1]
print(sorted_desc)
OrderedSetを使う
Python標準ライブラリにはOrderedSet
は存在しませんが、ordered-set
パッケージを使用すると簡単に実現できます。
# インストールが必要
# pip install ordered-set
from ordered_set import OrderedSet
ordered_set = OrderedSet([3, 1, 4, 1, 5, 9, 2, 6])
print(ordered_set) # OrderedSet([3, 1, 4, 5, 9, 2, 6])
この方法を使うと、リストのように要素の順序を維持しながら、set
の特性(重複なし)を利用できます。
まとめ
- Pythonの
set
は順序を保持しない(CPython 3.6以降では見た目上保持しているように見えるが保証されない)。 - 順序が必要な場合は
sorted()
を使う。 - 順序を維持しながら集合を扱いたい場合は、リストや辞書、
OrderedSet
を活用する。