117

我正在研究猜谜游戏的人工智能部分。我想让 AI 从这个列表中随机选择一个字母。我将其作为一组进行,因此我可以轻松地从列表中删除字母,因为它们在游戏中被猜到,因此不再可以再次被猜到。

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

import random 
aiTurn=True

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



    print (aiGuess) 
4

5 回答 5

119

注意(2020 年 10 月):从 v3.9 开始,Python 已正式弃用 random.sample()在集合上工作,官方指导是在传入之前将集合显式转换为列表或元组,但这并不能解决效率问题.


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

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

请注意,无论您如何操作,从集合中选择随机元素的效率都非常低- 它所花费的时间与集合的大小成正比,或者如果集合的底层哈希表由于删除的元素而变得稀疏,则更糟。

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

于 2013-04-05T15:29:10.080 回答
69

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

于 2014-07-25T06:53:27.227 回答
1

list您可以通过使用 a而不是a 来解决此问题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]
于 2021-02-20T06:52:59.343 回答
1

由于选择列表不是很长,您可以先使用 random.shuffle 列表。然后迭代列表中的每个元素。这样可以避免从列表中一一删除元素,并使您的代码更简洁。

于 2021-03-14T03:23:31.593 回答
1

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

a = set()
for i in range(10):
    a.add(i)
a.pop() // gives a random element from a set
于 2021-07-28T04:23:59.977 回答