如何获取线性下降随机分布?

1 投票
1 回答
596 浏览
提问于 2025-04-16 14:59

目前在Django中,我实现了在主页上随机显示人物。但现在我需要根据他们的重要性(用数字表示)来显示这些人物。

比如说:

名字|排序关键字
约翰| 5
汤姆 | 8

约翰应该被显示得更频繁一些。

person_number = random.randrange(Person.objects.count())
context = { 'person': Person.objects.all()[person_number], }

我试过使用random.expovariate,但这样会导致第一个人出现得太频繁。那么我应该使用随机库中的哪个函数呢?

更新:
基本上,像randrange(10)这样会给出[6,2,8,6,4,1,9,5,3,0],我需要一个算法,能够生成类似于[1,7,3,1,2,2,3,4,1,5,0]的结果。
1 - 最常出现(3次),2 - 较少(2次)等等。

1 个回答

5

我猜你是想要一个加权随机选择。基本上,你需要:

  1. 创建一个包含权重累加和的列表。
  2. 选择一个随机值,范围在[0, 权重总和-1]之间。
  3. 找到这个随机值对应的索引。

在Python中,用函数式的方法来实现(ireduce = scanl = partial_sum = ...),可以像这样:

import operator
import bisect
import random

def ireduce(f, state, it):
    """Accumulative reduce. ireduce(operator.sum, 0, [1, 2, 3, 4]) -> 1, 3, 6, 10."""
    for x in it:
        state = f(state, x)
        yield state

people = [
  {"name": "Iain David", "weight": 1}, 
  {"name": "John Martyn", "weight": 2},
]
weights = (person["weight"] for person in people)  
accumulated_weights = list(ireduce(operator.add, 0, weights))
random_value = random.randrange(accumulated_weights[-1])
index = bisect.bisect_right(accumulated_weights, random_value)
random_person = people[index]["name"] 
# "Iain David" (p=1/3), "John Martyn" (p=2/3)

撰写回答