从集合中随机选择?

问题描述 投票:0回答:7

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

它表示

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

import random

aiTurn = True
while aiTurn == True:
    allLetters = set(list('abcdefghijklmnopqrstuvwxyz'))
    aiGuess = random.choice(allLetters)
    print(aiGuess) 
python list random set
7个回答
144
投票

注意(2020 年 10 月): 自 v3.9 起,Python 正式弃用

random.sample()
在集合上工作,官方指导是在传入集合之前将集合显式转换为列表或元组这并不能解决效率问题。


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

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

请注意,无论你怎么做,从集合中选择随机元素都是极其低效的——它所花费的时间与集合的大小成正比,或者如果集合的基础哈希表由于删除的元素而变得稀疏,情况会更糟。

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


76
投票

您应该使用

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%。


1
投票

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


0
投票

您可以使用

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]

0
投票

在这种情况下,集合来自字符串,因此您可以使用字符串进行随机选择。

LETTERS = 'abcdefghijklmnopqrstuvwxyz'

allLetters = set(LETTERS)
aiGuess = random.choice(LETTERS)
print(aiGuess)

(这也避免了魔法常数。)


就我而言,我使用类似的解决方案遇到了同样的问题。我正在从文件中读取单词,并且我想随机选择一个选项并将其转换为一组,以便快速进行成员资格检查。最终最简单的是将其读入列表,然后做出选择,将列表转换为集合,然后删除列表(隐式地因为这是在函数中)。


-1
投票

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


-4
投票

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

a = set()
for i in range(10):
    a.add(i)
a.pop() // gives a random element from a set
© www.soinside.com 2019 - 2024. All rights reserved.