来自set的random.choice?蟒蛇


93

我正在做一个猜谜游戏的AI部分。我希望AI从此列表中选择一个随机字母。我将其设置为一组,这样我就可以轻松地从列表中删除字母,因为它们在游戏中会被猜测出来,因此不再可供再次猜测。

它说set对象不可索引。我该如何解决?

import random 
aiTurn=True

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



    print (aiGuess) 

1
顺便说一句,您不需要使用set(list('string'))来获取一组字母,因为字符串本身是可迭代的-set('abc')会做您想要的事情。
Scott Ritchie

5
对于其他遇到此问题的人,值得研究一下有关如何创建允许有效随机选择的类集合对象的问题。此处给出的选项均为O(N)。 stackoverflow.com/q/15993447/2966723
乔尔(Joel)

Answers:


91
>>> random.sample(set('abcdefghijklmnopqrstuvwxyz'), 1)
['f']

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


9
[0]最后加上a ,因此它基本上与random.choice(不会返回列表形式的值)相同
Nick T

31
random.sampletuple(population)内部执行,因此random.choice(tuple(allLetters))可能会更好。
utapyngo 2014年

21
应该强调的是,这个过程是O(N)。
乔尔

@Joel为什么这个过程是O(N)?
ManuelSchneid3r

2
我认为这确实效率不高...正如您所看到的github.com/python/cpython/blob/2.7/Lib/random.py#L332-L339,每次您进行上述调用时,示例函数都会从集合中创建一个列表,并且从中获取一个随机元素。假设您有一大套,并且要制作很多样本。如果集合没有改变,最好将其转换为列表并使用random.choice。如果在采样时集合也发生变化,则可能根本不应该使用集合。如果您知道集合中的哈希值和存储桶大小,那么编写采样函数将很容易...
jakab922

58

您应该使用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

从数字看来,这random.sample需要花费7%的时间。


2
在我的机器上,random.choice快7倍。
noɥʇʎԀʎzɐɹƆ

4
有没有办法直接从集合中进行选择,而不必将其复制到元组中?
Youda008

我得到的样本比在一组5000个元素上选择的样本慢大约12%(250毫秒)。
西蒙

1
在我的机器上,随着设置大小的增长,速度random.sample从慢random.choice到快(交叉点在设置大小100k-500k之间)。也就是说,集合越大,越可能random.sample需要更快。
jakee '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.