假设如下:
>>> s = set([1, 2, 3])
我如何得到一个值(任何值)不做s.pop()?我希望将项目留在集合中,直到我确定可以删除它—只有在对另一个主机进行异步调用之后才能确定这一点。
又快又脏:
>>> elem = s.pop()
>>> s.add(elem)
但你知道更好的办法吗?理想情况是在常数时间内。
假设如下:
>>> s = set([1, 2, 3])
我如何得到一个值(任何值)不做s.pop()?我希望将项目留在集合中,直到我确定可以删除它—只有在对另一个主机进行异步调用之后才能确定这一点。
又快又脏:
>>> elem = s.pop()
>>> s.add(elem)
但你知道更好的办法吗?理想情况是在常数时间内。
当前回答
s.copy().pop()怎么样?我还没有计时,但应该可以,而且很简单。但是,它最适用于小集,因为它复制了整个集。
其他回答
最少的代码是:
>>> s = set([1, 2, 3])
>>> list(s)[0]
1
显然,这将创建一个包含集合中的每个成员的新列表,所以如果你的集合非常大,就不太好了。
我用的是我写的效用函数。它的名字有点误导,因为它暗示它可能是一个随机的项目或类似的东西。
def anyitem(iterable):
try:
return iter(iterable).next()
except StopIteration:
return None
s.copy().pop()怎么样?我还没有计时,但应该可以,而且很简单。但是,它最适用于小集,因为它复制了整个集。
看似最紧凑(6个符号),但非常慢的方法来获得一个集合元素(由PEP 3132实现):
e,*_=s
使用Python 3.5+,你也可以使用这个7符号表达式(感谢PEP 448):
[*s][0]
在我的机器上,这两个选项都比for循环方法慢大约1000倍。
因为你想要一个随机元素,这也可以:
>>> import random
>>> s = set([1,2,3])
>>> random.sample(s, 1)
[2]
文档中似乎没有提到random.sample的性能。从一个非常快速的经验测试中,有一个巨大的列表和一个巨大的集合,对于列表来说似乎是常数时间,而对于集合来说则不是。而且,集合上的迭代不是随机的;顺序没有定义,但可以预测:
>>> list(set(range(10))) == range(10)
True
如果随机性很重要,并且你需要在常数时间内(大型集合)使用一堆元素,那么我会使用随机性。先采样并转换为列表:
>>> lst = list(s) # once, O(len(s))?
...
>>> e = random.sample(lst, 1)[0] # constant time