はじめに
「あるよ。」nikkieです。
PyPIを探したら簡単に見つかると思ったのですが、存外時間がかかったので備忘録にします。
「メンテされている」が狭き門でしたね。
目次
挿入順序を保存したsetがほしい!
まずPythonは、3.7から辞書(dict
)が挿入順序を保存します。
https://docs.python.org/ja/3/whatsnew/3.7.html#summary-release-highlights
dict オブジェクトの挿入順序を保存するという性質が、公式に Python 言語仕様の一部であると 宣言されました (「Python のデータモデルの改善」より)
3.6以前で挿入順序を保存した辞書を使いたい場合、collections.OrderedDict
があったという理解です。
https://docs.python.org/ja/3/library/collections.html#ordereddict-objects
組み込みの dict クラスが挿入順序を記憶しておく機能 (略) を獲得した今となっては、順序付き辞書の重要性は薄れました。
「重要性は薄れた」とありますが、挿入順序を保存したdict
はOrderedDict
と同じものではなく、OrderedDict
は並べ替え操作に向くようです。
OrderedDict のアルゴリズムは、頻繁な並べ替え処理を dict よりもうまく扱うことができます。
今回は、3.7以降のdict
やcollections.OrderedDict
のset版、挿入順序が保存されたset(集合)が欲しくなりました。
標準ライブラリにはないという認識なので、PyPIで探していきました(最初はすぐ見つかるだろうと思っていたんですよね)
結論:あるよ。
boltonsを使うのです。
Awesome PythonのMiscellaneousにも載っていますよ。
https://pypi.org/project/boltons/
Pythonには標準ライブラリにOrderedSetがないのですが、「PyPIにあるやろ!」と調べ始め、
— nikkie(にっきー) / にっP (@ftnext) 2025年1月26日
検索して「めっちゃ出てきた!」->「これは、メンテされてない〜」を繰り返した挙げ句、boltonsってやつがよさそうでした。
botlonsのIndexedSetはOrderedSet的振る舞いするやつと理解https://t.co/9aFLQcFjDz
% uv run --python 3.13 --with boltons python >>> # Python 3.13.0, boltons 24.1.0 です >>> from boltons.setutils import IndexedSet >>> IndexedSet("abcb") IndexedSet(['a', 'b', 'c']) >>> IndexedSet("abcb") - set("db") IndexedSet(['a', 'c']) >>> IndexedSet("abcb") - set("d") IndexedSet(['a', 'b', 'c'])
以下はboltonsにたどり着くまでの過程です
メンテされている、挿入順序を記憶したsetのライブラリ探し
まずPyPIを「orderedset」で検索すると、いっぱい出てきます。
https://pypi.org/search/?q=orderedset
ひとつひとつ見ていくのは骨が折れそうだったので、ググって上位の記事から辿ることにしました。
Pythonのdiscussから
https://discuss.python.org/t/add-orderedset-to-stdlib/12730/3 より
どちらもメンテされていると思えなかったので不採用です
ordered-set(最終リリース 2022年1月)
使用例から、挿入順を記憶する機能を持ったsetと見受けましたが、
>>> letters = OrderedSet('abracadabrashazam') >>> letters OrderedSet(['a', 'b', 'r', 'c', 'd', 'x', 's', 'h', 'z', 'm']) >>> letters -= 'abcd' >>> letters OrderedSet(['r', 'x', 's', 'h', 'z', 'm'])
PyPIへのリリースは2022年1月が最後。
GitHub(200 star)はpatchのプルリクエストが取り込まれているようですが、PyPIへのリリースは止まってしまっています
orderedset(最終リリース 2020年2月)
使用例から、挿入順を記憶する機能を持ったsetと見受けましたが、
>>> OrderedSet([1, 2, 3]) | [5, 4, 3, 2, 1] OrderedSet([1, 2, 3, 5, 4])
PyPIへのリリースは2020年2月が最後。
GitHub(70 star)も同時期に更新が止まっています
Stack Overflowから
上記のdiscussからもリンクされており、検索も上位に出てきた質問
「insertion-order preserving set」について、PyPIのパッケージを紹介する回答 https://stackoverflow.com/a/23225031 より
- ordered-set(上述)
- collections-extended
- boltons(本記事の結論)
collections-extendedはメンテされていると思えなかったので不採用です
collections-extended(最終リリース 2022年1月)
これは使用例から欲しいものかがパッと分かっていません。
setlist
の差集合の例が見つかりませんでした(要・素振り)
PyPIへのリリースは2022年1月が最後。
GitHub(40 star)も同じ年に更新が止まっています
Awesome Pythonから
途中で「Awesome Pythonで紹介されてるんじゃない?」と思い見てみました。
「Algorithms and Design Patterns」
sortedcontainers - Fast and pure-Python implementation of sorted collections.
お!
sortedcontainers(最終リリース 2022年1月)
https://pypi.org/project/sortedcontainers/
使用例からSortedSet
がそれっぽいですが、差集合の例は見つかりませんでした(要・素振り)
PyPIへのリリースは2022年1月が最後。
GitHub(3600 star)は動きがありますが、「それをPyPIへリリースしてくり〜。頼む〜🙏」という気持ちです
メンテされていると思えなかったので不採用です
終わりに
Pythonで挿入順序を保存したsetで、メンテされているライブラリとして私が今回見つけたのはboltonsです。
挿入順序を保存したset以外にも色々と提供してそうで、boltonsは仲良くなりたいパッケージですね。
それにしても、Pythonコミュニティ、挿入順序を保存したsetのパッケージを作りすぎてますね。
私はTwitterのいいねのように結構軽率にstarしていくのですが、メンテされていないと判断したパッケージにstarするのは控えようかなと今回思いました