来自set的选择?蟒蛇

jam*_*myn 65 python list set

我正在研究一个猜谜游戏的AI部分.我希望AI从这个列表中选择一个随机字母.我正在做它作为一个集合,所以我可以轻松删除列表中的字母,因为它们在游戏中猜到,因此不再可以再次猜到.

它说"set"对象不可索引.我该如何解决这个问题?

import random 
aiTurn=True

while aiTurn == True:
    allLetters = set(list('abcdefghijklmnopqrstuvwxyz'))
    aiGuess=random.choice(allLetters)



    print (aiGuess) 
Run Code Online (Sandbox Code Playgroud)

NPE*_*NPE 77

>>> random.sample(set('abcdefghijklmnopqrstuvwxyz'), 1)
['f']
Run Code Online (Sandbox Code Playgroud)

文档:https://docs.python.org/3/library/random.html#random.sample

  • `random.sample`在内部做`tuple(population)`所以`random.choice(tuple(allLetters))`可能更好. (24认同)
  • 应该强调的是,这个过程是O(N). (11认同)
  • 在末尾添加一个`[0]`所以它基本上与`random.choice`相同(它不会以列表的形式返回它的值) (7认同)
  • 我认为这真的很低效......正如你所看到的 https://github.com/python/cpython/blob/2.7/Lib/random.py#L332-L339 每次你制作时,示例函数都会从集合中创建一个列表上面的调用并从中获取一个随机元素。假设你有一个很大的集合并且你想要制作很多样本。如果集合没有改变,最好将其转换为列表并使用 `random.choice`。如果在您采样时该集合也发生了变化,那么您可能根本不应该使用该集合。如果你知道集合中被占用的哈希值和桶的大小,那么编写一个采样函数就很容易了...... (3认同)
  • 请注意,从 3.9 开始,Python [正式弃用](https://docs.python.org/3.9/library/random.html#random.sample) `random.sample()` 在集合上工作,官方指导是在传入之前将集合显式转换为列表或元组。 (3认同)

Sco*_*hie 48

你应该使用random.choice(tuple(myset)),因为它比random.sample更快,更清晰.我写了以下内容进行测试:

import random
import timeit

bigset = set(random.uniform(0,10000) for x in range(10000))

def choose():
    random.choice(tuple(bigset))

def sample():
    random.sample(bigset,1)[0]

print("random.choice:", timeit.timeit(choose, setup="global bigset", number=10000)) # 1.1082136780023575
print("random.sample:", timeit.timeit(sample, setup="global bigset", number=10000)) # 1.1889629259821959
Run Code Online (Sandbox Code Playgroud)

从数字看,random.sample需要7%的时间.

  • 在我的机器上,random.choice 快了 7 倍。 (2认同)
  • 有没有办法直接从集合中进行选择,而不必将其复制到元组中? (2认同)