【Python】setにおけるorder(順序)

【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を活用する。
コメントは受け付けていません。