92494
原因／対処法が不明のため、質問させてください  
以下のコードのように10個ある要素の組み合わせをすべて出し、それをタプルから集合に変換しました

```

    #要素の個数
    J = 10
    
    #要素の全組み合わせ
    subsets = [
        s
        for j in range(J + 1)
        for s in combinations(range(J), j)
    ]
    
    #各組合せをタプル⇒集合に変換。左に元のタプル型、右に集合として並べて比べてみる
    for j in range(J):
        for s_union_j in subsets:
            s_union_j_set = set(s_union_j)
            print (s_union_j, s_union_j_set) 
            
    
```

その結果、以下のように元のタプルと集合が出力されますが、このときなぜか(X, 8又は9)
(Xは8未満)となっているものに関しては、(8又は9,X)のように値のカッコ内の位置が逆転してしまいます (黄色ハイライト参照)  
8以上の値のときこの事象が起こり、それ以下の値のときは逆転は起こらないようです

[![画像の説明をここに入力](https://i.stack.imgur.com/bjNV4.png)](https://i.stack.imgur.com/bjNV4.png)

こちらの原因としては何で、元の順序関係を保持したまま集合に変換するにはどのようにすればよいでしょうか

よろしくおねがいします
CC BY-SA 4.0
2022-11-29T05:59:44.327
92491
2022-11-30T05:46:04.713
44061
question
python
タプルから集合に変換すると"8"の順序が逆転する
sorted(s_union_j_set)とすれば元のタプルの順序関係に戻すことができますが、なぜ8以上の数値があると順序が逆転するのか、後学のためご存知の方がいらっしゃいましたらご教示いただけますと幸いです。
CC BY-SA 4.0
2022-11-29T06:19:27.023
92492
2022-11-29T06:19:27.023
44061
92491
answer
想像を多分に含んだ話です。

* * *

pythonの`set`はハッシュテーブルで実装しているそうです。

例えば`[1,2,8]`を`set`に変換すると  
十分少ない要素のsetに対してはルート配列の要素が8、  
つまりハッシュ値を8で割った余りごとにまとめて管理していると仮定して  
数値オブジェクトのハッシュはたいてい数値そのままなので

```

    [
    [8], # 0
    [1], # 1
    [2], # 2
    [], # 3
    [], # 4
    [], # 5
    [], # 6
    [], # 7
    ]
    
```

という内部構造になり、`print`するときはおそらく先頭から順番に表示するので  
質問のような現象が起こるのではないでしょうか。

実際何が起きているかはCPythonのコード  
<https://github.com/python/cpython/blob/main/Objects/setobject.c>  
を読めばわかりそうです。私は諦めました。
CC BY-SA 4.0
2022-11-29T06:52:10.133
92494
2022-11-29T07:08:59.673
2022-11-29T07:08:59.673
13127
13127
92491
answer
> 元の順序関係を保持したまま集合に変換するにはどのようにすればよいでしょうか

不可能です。Python言語の`set`(集合)型は
[順序なしコレクション](https://docs.python.org/ja/3/library/stdtypes.html#set-types-set-
frozenset) と規定されますから、`set`型に変換した時点で順序に関する保証は一切なくなります。

Python処理系毎に結果は変化する可能性があります。

  * CPython 3.10の例：<https://wandbox.org/permlink/MYtuvLz2oAvLwmyl>
  * pypy7.3の例：<https://wandbox.org/permlink/5Jt0WwNfzm74x9vk>
CC BY-SA 4.0
2022-11-30T05:46:04.713
92510
2022-11-30T05:46:04.713
49
92491
answer