随机选择? 巨蟒

我在研究猜谜游戏的人工智能部分。我希望人工智能从这个列表中随机选择一个字母。我这样做作为一个集,所以我可以很容易地删除列表中的字母,因为他们是在游戏中猜测,因此不再可用于猜测了。

它说 set对象是不可转位的。我如何解决这个问题?

import random
aiTurn=True


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






print (aiGuess)
150378 次浏览

注意(2020年10月) : 在3.9版本中,Python 使用 正式废除 random.sample()处理集合,官方指导是在传递集合之前显式地将其转换为 list 或 tuple,尽管这并不能解决效率问题。


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

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

请注意,从一个集合中选择随机元素是 效率极低,无论你怎么做-这需要时间与集合的大小成比例,或者更糟糕的是,如果集合的基础散列表是稀疏的,由于删除的元素。

相反,您可能应该使用一个有效支持此操作的 不同的数据结构

你应该使用 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% 的时间。

您可以使用 list而不是 set来解决这个问题。您仍然可以“轻松地”从列表中删除字母。试试这个,例如:

allLetters = list('abcdefghijklmnopqrstuvwxyz')
aiGuess = random.choice(allLetters)
allLetters.remove(aiGuess)

另一种选择是随机选择索引而不是字母,这样可能会稍微快一点,因为我们不需要搜索要删除的元素(但是我怀疑速度在这里是否真的重要?):

allLetters = list('abcdefghijklmnopqrstuvwxyz')
index = random.randint(0, len(allLetters)-1) # Top is inclusive, unlike slices
aiGuess = allLetters[index]
del allLetters[index]

因为选择列表不是很长,所以可以先使用 Random. shuffle 列表。然后迭代列表中的每个元素。这样可以避免逐个从列表中删除元素,并使代码更清晰。

如果要从集合中获取随机元素。

a = set()
for i in range(10):
a.add(i)
a.pop() // gives a random element from a set

您可以组合一个双链表和一个字典,以创建一个 O (1)随机选择的集合。