random.choice dari set? python

94

Saya sedang mengerjakan bagian AI dari game menebak. Saya ingin AI memilih huruf acak dari daftar ini. Saya melakukannya sebagai satu set sehingga saya dapat dengan mudah menghapus huruf dari daftar seperti yang ditebak dalam permainan dan karena itu tidak lagi tersedia untuk ditebak lagi.

dikatakan setobjek tidak dapat diindeks. Bagaimana saya bisa mengatasi ini?

import random 
aiTurn=True

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



    print (aiGuess) 
jamyn
sumber
1
Kebetulan Anda tidak perlu menggunakan set (list ('string')) untuk mendapatkan sekumpulan huruf karena string dapat diulang dengan sendirinya - set ('abc') akan melakukan apa yang Anda inginkan.
Scott Ritchie
5
Bagi orang lain yang mengalami masalah ini, ada baiknya melihat pertanyaan ini tentang cara membuat objek seperti set yang memungkinkan pemilihan acak yang efisien. Opsi yang diberikan di sini semuanya O (N). stackoverflow.com/q/15993447/2966723
Joel

Jawaban:

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

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

NPE
sumber
9
Tack [0]di akhir sehingga pada dasarnya identik dengan random.choice(yang tidak mengembalikan nilainya dalam bentuk daftar)
Nick T
31
random.samplelakukan secara tuple(population)internal, jadi random.choice(tuple(allLetters))mungkin lebih baik.
utapyngo
21
Harus disorot bahwa proses ini adalah O (N).
Yoel
@ Joel Mengapa proses ini O (N)?
ManuelSchneid3r
2
Saya pikir itu benar-benar tidak efisien ... Seperti yang Anda lihat github.com/python/cpython/blob/2.7/Lib/random.py#L332-L339 fungsi sampel membuat daftar dari set setiap kali Anda melakukan panggilan di atas dan mengambil elemen acak darinya. Misalkan Anda memiliki set yang besar dan Anda ingin membuat banyak sampel. Jika set tidak berubah, lebih baik mengubahnya menjadi daftar dan digunakan random.choice. Jika set juga berubah saat Anda mengambil sampel maka mungkin Anda tidak harus menggunakan set sama sekali. Jika Anda mengetahui hash yang ditempati dalam set dan ukuran bucket, akan mudah untuk menulis fungsi pengambilan sampel ...
jakab922
58

Anda harus menggunakan random.choice(tuple(myset)), karena lebih cepat dan bisa dibilang terlihat lebih bersih daripada random.sample. Saya menulis yang berikut untuk menguji:

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

Dari angka-angka itu sepertinya random.samplebutuh waktu 7% lebih lama.

Scott Ritchie
sumber
2
Di mesin saya, random.choice 7 kali lebih cepat.
noɥʇʎԀʎzɐɹƆ
4
Tidak ada cara untuk memilih langsung dari set, tanpa harus menyalinnya ke tuple?
Youda008
Saya mendapatkan sampel yang kira-kira 12% (250 ms) lebih lambat daripada memilih pada satu set 5000 elemen.
Simon
1
Di mesin saya, random.sampleberubah dari lebih lambat daripada random.choicemenjadi lebih cepat daripada saat ukuran yang ditetapkan tumbuh (titik persilangan berada di antara ukuran set 100k-500k). Artinya, semakin besar himpunannya, semakin besar kemungkinannya untuk random.samplemenjadi lebih cepat.
jakee