Python,从集合中转换列表会更改顺序。避免这种情况的最佳方法是什么?

Python, Casting a list from a set changes the order. What is the best way to avoid this?

鉴于此 python 代码片段:

import numpy as np
rng = np.random.default_rng(42)

class Agent:
    def __init__(self, id):
        self.id = id
        self.friends = set()

    def __repr__(self):
        return str(self.id)

group_list = list()
for i in range(100):
    new_obj = Agent(i)
    group_list.append(new_obj)

for person in group_list:
    pool = rng.choice([p for p in group_list if p != person], 6)
    for p in pool:
        person.friends.add(p)

def set_to_list_ordered(a_set):
    return sorted(list(a_set), key=lambda x: x.id)

print("This will change: ")
print(rng.choice(list(group_list[0].friends), 2))
print("This will not change: ")
print(rng.choice(set_to_list_ordered(group_list[0].friends), 2))

此代码的目的是从集合中随机提取 2 个元素。问题是 np.random.choiche 函数不接受集合,所以你必须把它变成一个列表。但是,这样做,元素的顺序是随机的,并且给定相同的种子,随机提取的结果是不可复制的。在这种情况下,我实现了一个对元素进行排序的函数,但是它的成本很高。

您会正确地说,使用列表而不是集合。对此我的回答是套装非常适合我需要的用途。例如,此结构允许 Agent.friends 属性没有重复元素。

所以,我的问题是,除了我实现的函数之外,使用集合并确定从集合中随机提取的最方便的方法是什么?使用列表而不是集合更好吗?有什么方法可以使转换具有确定性吗?

提前致谢。

编辑: 一些人观察到从集合到列表的转换在内部是一致的。我的 objective 是为了使这种转换在外部也保持一致。这样通过运行多次相同的脚本,default_rng实例的提取是相同的。

您可以使用 ordered set.

来自文档:

from ordered_set import OrderedSet

>>>OrderedSet('abracadabra')
OrderedSet(['a', 'b', 'r', 'c', 'd'])

通过覆盖 hash() 方法解决。资料来源:https://www.youtube.com/watch?v=C4Kc8xzcA68

import numpy as np
rng = np.random.default_rng(42)

class Agent:
    def __init__(self, id):
        self.id = id
        self.friends = set()

    def __repr__(self):
        return str(self.id)
   
    def __hash__(self):
        return self.id


group_list = list()
for i in range(100):
    new_obj = Agent(i)
    group_list.append(new_obj)

for person in group_list:
    pool = rng.choice([p for p in group_list if p != person], 6)
    for p in pool:
        person.friends.add(p)

def set_to_list_ordered(a_set):
    return sorted(list(a_set), key=lambda x: x.id)

print("This will change: ")
print(rng.choice(list(group_list[0].friends), 2))
print("This will not change: ")
print(rng.choice(set_to_list_ordered(group_list[0].friends), 2))