簡體   English   中英

Python:從具有權重但不重復的列表中隨機抽取 N 個項目

[英]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。 然而,有時同一個人被選為兩個獲勝者。 有沒有辦法為每個參賽者分配權重?

我嘗試使用帶有權weightsrandom.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM