สุ่มเลือกจากชุด? หลาม


95

ฉันกำลังทำส่วน AI ของเกมทายใจ ฉันต้องการให้ AI เลือกตัวอักษรแบบสุ่มจากรายการนี้ ฉันกำลังทำมันเป็นชุดเพื่อให้ฉันสามารถลบตัวอักษรออกจากรายการได้อย่างง่ายดายเนื่องจากเดาได้ในเกมดังนั้นจึงไม่สามารถเดาได้อีกต่อไป

มันบอกว่าsetออบเจ็กต์ไม่สามารถจัดทำดัชนีได้ ฉันจะแก้ไขปัญหานี้ได้อย่างไร

import random 
aiTurn=True

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



    print (aiGuess) 

1
บังเอิญคุณไม่จำเป็นต้องใช้ set (list ('string')) เพื่อรับชุดของตัวอักษรเนื่องจากสตริงสามารถทำซ้ำได้ด้วยตัวเอง set ('abc') จะทำสิ่งที่คุณต้องการ
Scott Ritchie

5
สำหรับคนอื่น ๆ ที่พบปัญหานี้คุณควรพิจารณาคำถามนี้เกี่ยวกับวิธีสร้างวัตถุที่มีลักษณะเป็นชุดซึ่งช่วยให้สามารถเลือกแบบสุ่มได้อย่างมีประสิทธิภาพ ตัวเลือกที่ระบุนี้คือ O (N) ทั้งหมด stackoverflow.com/q/15993447/2966723
Joel

คำตอบ:


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

@ 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

ฉันได้รับตัวอย่างช้ากว่าที่เลือกจากชุด 5,000 องค์ประกอบประมาณ 12% (250 มิลลิวินาที)
Simon

1
บนเครื่องของฉันเปลี่ยนrandom.sampleจากการทำงานช้ากว่าrandom.choiceเป็นเร็วกว่าเมื่อขนาดของชุดใหญ่ขึ้น (จุดครอสโอเวอร์อยู่ระหว่างชุดขนาด 100k-500k) นั่นคือยิ่งชุดมีขนาดใหญ่ก็ยิ่งมีโอกาสrandom.sampleที่จะเร็วขึ้น
jakee
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.