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


94

Я работаю над частью игры в угадайку, связанной с искусственным интеллектом. Я хочу, чтобы ИИ выбрал случайную букву из этого списка. Я делаю это как набор, поэтому я могу легко удалять буквы из списка, поскольку они угадываются в игре и поэтому больше не доступны для повторного угадывания.

он говорит, что 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
Джоэл

Ответы:


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

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


9
Прикрепите [0]в конце, так что он в основном идентичен random.choice(который не возвращает его значения в виде списка)
Nick T

31
random.sampleделает tuple(population)внутренне, так что random.choice(tuple(allLetters))может быть лучше.
utapyngo

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

Я получаю выборку примерно на 12% (250 мс) медленнее, чем выбор на наборе из 5000 элементов.
Саймон

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