[英]Python: Sample N random items from list with weights but without repetition
我正在創建一種彩票系統,其中個人(通過唯一 ID 識別)可以有多張彩票,但是一旦他們被選中,他們就不能被選中再次中獎。
這是我的例子:
import random
entrants = ['John', 'Jane', 'Cthulhu']
allEntries = []
for entrant in entrants:
numEntries = random.randint(1, 5)
print("%s has %d entries" % (entrant, numEntries))
allEntries.extend([entrant] * numEntries)
print(random.sample(allEntries, k=2))
我的想法是制作一個列表,其中包含entrant
的名稱numEntries
次,然后是 select。 然而,有時同一個人被選為兩個獲勝者。 有沒有辦法為每個參賽者分配權重?
我嘗試使用帶有權weights
的random.choices()
但這也可以 select 與兩個獲勝者相同的人。
import random
weights = []
for entrant in entrants:
numEntries = random.randint(1, 5)
print("%s has %d entries" % (entrant, numEntries))
weights.extend([numEntries])
print(random.choices(entrants, weights=weights, k=2))
做你想做的最簡單的方法是使用 NumPy。下面的 function 可以做到這一切:
numpy.random.choice(a, size=None, replace=True, p=None)
a
: array-like object (eg list) 你想從 select
size
: 元素數量到 select
replace
:表示是否允許多次 select 同一項目 - 在您的情況下為False
p
: array-like object (eg list) 具有 a 中元素的概率(相同順序)
參考: https://numpy.org/doc/stable/reference/random/generated/numpy.random.choice.html
select 隨機不重復的正常方法是打亂條目並取前 N。
from random import shuffle
N = 1
entrants = ['John', 'Jane', 'Cthulhu']
shuffle(entrants)
print(entrants[:N])
或者更直接
from random import sample
N = 1
entrants = ['John', 'Jane', 'Cthulhu']
print(sample(entrants, N))
但是,您對加權抽樣的要求意味着您需要的不止於此。
def unique_sample(population, count):
shuffle(population)
unique = set()
it = iter(population)
while len(unique) < count:
elem = next(it)
if elem not in unique:
yield elem
unique.add(elem)
我喜歡將參賽者姓名乘以參賽作品數量的解決方案。 我的解決方案的問題是,如果我選擇了一個獲勝者,他們仍然在池中。
import random
def selectWinners(allEntries, numWinners):
winners = []
print("Selecting %d winners" % numWinners)
print("Entries", allEntries)
for i in range(numWinners):
winner = random.choice(allEntries)
print("%d: %s won" % (i+1, winner))
allEntries[:] = [x for x in allEntries if x != winner]
entrants = ['John', 'Jane', 'Cthulhu']
allEntries = []
for entrant in entrants:
numEntries = random.randint(1, 5)
print("%s has %d entries" % (entrant, numEntries))
allEntries.extend([entrant] * numEntries)
selectWinners(allEntries, 2)
返回 output,例如:
John has 1 entries
Jane has 1 entries
Cthulhu has 5 entries
Selecting 2 winners
Entries ['John', 'Jane', 'Cthulhu', 'Cthulhu', 'Cthulhu', 'Cthulhu', 'Cthulhu']
1: Cthulhu won
2: Jane won
我正在創建一種彩票系統,其中個人(通過唯一 ID 標識)可以將多張彩票放入彩票中,但是一旦他們被選中,就無法再次中獎。
這是我的例子:
import random
entrants = ['John', 'Jane', 'Cthulhu']
allEntries = []
for entrant in entrants:
numEntries = random.randint(1, 5)
print("%s has %d entries" % (entrant, numEntries))
allEntries.extend([entrant] * numEntries)
print(random.sample(allEntries, k=2))
我的想法是制作一個包含entrant
名稱numEntries
次的列表,然后從那里進行選擇。 然而,有時同一個人被選為兩個獲勝者。 有沒有辦法為每個參賽者設置權重?
我嘗試使用帶random.choices()
weights
random.choices()
但這也可以選擇同一個人作為兩個獲勝者。
import random
weights = []
for entrant in entrants:
numEntries = random.randint(1, 5)
print("%s has %d entries" % (entrant, numEntries))
weights.extend([numEntries])
print(random.choices(entrants, weights=weights, k=2))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.