random.choice з набору? пітон


93

Я працюю над ІІ частиною гри в відгадування. Я хочу, щоб ШІ вибрав випадкову літеру з цього списку. Я роблю це як набір, щоб я міг легко вилучати літери зі списку, оскільки вони вгадуються в грі і тому більше не доступні для повторного вгадування.

там сказано, що setоб’єкт не можна індексувати. Як я можу обійти це?

import random 
aiTurn=True

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



    print (aiGuess) 

1
До речі, вам не потрібно використовувати set (list ('string')), щоб отримати набір літер, оскільки рядки є ітерабельними самі по собі - set ('abc') зробить те, що ви хочете.
Скотт Річі,

5
Іншим, хто стикається з цією проблемою, варто розглянути це питання про те, як створити подібний до набору об’єкт, що дозволяє здійснювати ефективний випадковий вибір. Усі наведені тут варіанти - O (N). stackoverflow.com/q/15993447/2966723
Джоель

Відповіді:


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

Документація: https://docs.python.org/3/library/random.html#random.sample


9
Закріпіть на [0]кінці, щоб він в основному ідентичний random.choice(що не повертає його значення у вигляді списку)
Нік Т

31
random.sampleробить tuple(population)внутрішньо, тому random.choice(tuple(allLetters))може бути і краще.
utapyngo

21
Слід підкреслити, що цей процес є O (N).
Джоель

@ Джоел Чому цей процес має значення 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

Я отримую, що зразок приблизно на 12% (250 мс) повільніший, ніж вибір набору з 5000 елементів.
Саймон

1
На моїй машині random.sampleвідбувається random.choiceперехід від повільнішого, ніж швидший, ніж збільшується розмір набору (точка перетину знаходиться десь між встановленим розміром 100k-500k). Тобто, чим більший набір, тим більше шансів random.sampleбути швидшим.
jakee
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.