模板 1:通用数据结构模板 (Python)

这是最基础、最核心的模板,适用于大多数编程语言,它通常是一个由 (元素, 权重) 对组成的列表。

数据结构定义

# 类型别名,增加代码可读性
WeightedItem = tuple[any, float | int] # 元素可以是任何类型,权重是整数或浮点数
class WeightList:
    def __init__(self):
        """初始化一个空的权重列表"""
        self.items: list[WeightedItem] = []
    def add(self, item: any, weight: float | int):
        """添加一个元素及其权重"""
        if weight <= 0:
            raise ValueError("权重必须大于0")
        self.items.append((item, weight))
    def remove(self, item: any):
        """移除一个元素(如果存在)"""
        self.items = [(i, w) for i, w in self.items if i != item]
    def get_total_weight(self) -> float | int:
        """计算所有权重之和"""
        return sum(weight for _, weight in self.items)
    def __len__(self) -> int:
        """返回元素的数量"""
        return len(self.items)
    def __str__(self) -> str:
        """返回列表的字符串表示"""
        return str(self.items)

使用示例

# 创建一个权重列表
wl = WeightList()
wl.add("苹果", 10)
wl.add("香蕉", 5)
wl.add("橙子", 3)
# 打印列表和总权重
print(f"权重列表: {wl}")
print(f"总权重: {wl.get_total_weight()}")  # 输出: 18
# 移除一个元素
wl.remove("香蕉")
print(f"移除香蕉后: {wl}")
print(f"新的总权重: {wl.get_total_weight()}") # 输出: 13

模板 2:带随机选择功能的模板 (Python)

这是“权重列表”最常见的应用场景之一,用于根据权重进行随机抽样。

数据结构定义

在模板1的基础上,增加随机选择功能。

import random
class WeightedRandomSelector(WeightList):
    def __init__(self):
        """初始化权重随机选择器"""
        super().__init__()
        self._total_weight = 0  # 缓存总权重,提高效率
    def add(self, item: any, weight: float | int):
        """添加元素并更新总权重缓存"""
        super().add(item, weight)
        self._total_weight += weight
    def remove(self, item: any):
        """移除元素并更新总权重缓存"""
        # 需要先找到要移除的权重
        item_to_remove = next((i for i, w in self.items if i == item), None)
        if item_to_remove:
            _, weight_to_remove = next((i, w) for i, w in self.items if i == item)
            super().remove(item)
            self._total_weight -= weight_to_remove
    def get_total_weight(self) -> float | int:
        """返回缓存的或计算的总权重"""
        return self._total_weight
    def choose_one(self) -> any:
        """
        根据权重随机选择一个元素。
        这是核心算法,使用轮盘赌选择法。
        """
        if not self.items:
            raise ValueError("权重列表为空,无法选择")
        # 1. 生成一个 [0, total_weight) 范围内的随机数
        point = random.uniform(0, self._total_weight)
        # 2. 遍历列表,累加权重,直到累加值大于随机数
        current_weight = 0
        for item, weight in self.items:
            current_weight += weight
            if point < current_weight:
                return item
        # 理论上不会执行到这里,但为了健壮性
        return self.items[-1][0]
    def choose_n(self, n: int) -> list[any]:
        """随机选择 n 个元素(可重复)"""
        return [self.choose_one() for _ in range(n)]

使用示例

# 创建一个抽奖箱
lottery_box = WeightedRandomSelector()
lottery_box.add("一等奖", 1)
lottery_box.add("二等奖", 5)
lottery_box.add("三等奖", 10)
lottery_box.add("谢谢参与", 84)
print(f"抽奖箱内容: {lottery_box}")
print(f"总权重 (总概率): {lottery_box.get_total_weight()}")
# 模拟抽奖100次
results = lottery_box.choose_n(100)
print(f"抽奖100次结果统计:")
print(f"一等奖: {results.count('一等奖')} 次")
print(f"二等奖: {results.count('二等奖')} 次")
print(f"三等奖: {results.count('三等奖')} 次")
print(f"谢谢参与: {results.count('谢谢参与')} 次")

输出结果会非常接近权重比例,例如一等奖大约出现1次,二等奖5次,三等奖10次。


模板 3:Excel / Google Sheets 实现模板

在电子表格中实现权重列表非常直观,常用于随机抽样、加权平均等计算。

结构设计

A B C D
1 项目/选项 权重 随机数 (辅助列) 随机选择结果
2 苹果 10 =RAND() =IF(D2=MIN($D$2:$D$5), A2, "")
3 香蕉 5 =RAND() =IF(D3=MIN($D$2:$D$5), A3, "")
4 橙子 3 =RAND() =IF(D4=MIN($D$2:$D$5), A4, "")
5 葡萄 2 =RAND() =IF(D5=MIN($D$2:$D$5), A5, "")

使用方法

  1. 输入数据:在 A 列和 B 列输入你的项目和对应的权重。
  2. 生成随机数:在 C2 单元格输入公式 =RAND(),然后向下拖动填充柄,这个函数会为每一行生成一个 0 到 1 之间的随机数。
  3. 随机选择
    • 简单随机选择=VLOOKUP(MIN($C$2:$C$5), $A$2:$B$5, 1, FALSE) 这个公式会找到随机数最小值对应的项目。
    • 按权重随机选择:这是一个更复杂但更公平的方法,需要用到辅助列和 MATCH/INDEX 组合,一个经典的技巧是,权重越高的项目,其随机数应该越小,上面的 D 列公式就是一种实现方式:它找到随机数最小的那一行,并返回对应的项目,每次按 F9 刷新,都会进行一次新的随机选择。

模板 4:HTML / JavaScript 前端实现模板

在网页中,权重列表常用于实现“轮盘抽奖”、“广告随机展示”等功能。

HTML 结构

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">权重列表抽奖</title>
</head>
<body>
    <h1>点击按钮进行抽奖</h1>
    <button id="drawButton">抽奖</button>
    <p id="result"></p>
    <script src="weighted_list.js"></script>
</body>
</html>

JavaScript 实现 (weighted_list.js)

class WeightedList {
    constructor() {
        this.items = [];
        this.totalWeight = 0;
    }
    add(item, weight) {
        if (weight <= 0) {
            throw new Error("权重必须大于0");
        }
        this.items.push({ item, weight });
        this.totalWeight += weight;
    }
    chooseOne() {
        if (this.items.length === 0) {
            throw new Error("权重列表为空");
        }
        // 生成一个 [0, totalWeight) 范围内的随机数
        const point = Math.random() * this.totalWeight;
        let currentWeight = 0;
        for (const entry of this.items) {
            currentWeight += entry.weight;
            if (point < currentWeight) {
                return entry.item;
            }
        }
        // 理论上不会执行到这里
        return this.items[this.items.length - 1].item;
    }
}
// --- 使用示例 ---
document.addEventListener('DOMContentLoaded', () => {
    const prizeList = new WeightedList();
    prizeList.add("一等奖 (iPhone)", 1);
    prizeList.add("二等奖 (iPad)", 5);
    prizeList.add("三等奖 (AirPods)", 10);
    prizeList.add("谢谢参与 (优惠券)", 84);
    const drawButton = document.getElementById('drawButton');
    const resultElement = document.getElementById('result');
    drawButton.addEventListener('click', () => {
        const prize = prizeList.chooseOne();
        resultElement.textContent = `恭喜您获得: ${prize}!`;
    });
});
场景 核心数据结构 关键操作/算法 适用工具/语言
通用数据存储 (元素, 权重) 元组列表 增加、删除、求和 Python, Java, C++, Go 等
随机抽样/抽奖 (元素, 权重) 元组列表 轮盘赌算法 Python, JavaScript, Excel
加权平均/计算 (数值, 权重) 元组列表 Σ(数值 * 权重) / Σ(权重) Excel, Python, R, MATLAB
路径查找/AI (节点/动作, 概率) 元组列表 归一化、概率分布采样 Python (NumPy), C++, TensorFlow/PyTorch

选择哪个模板取决于您的具体需求,如果您只是想存储带权重的数据,模板1足够了,如果您需要根据权重进行随机选择,模板2模板4是最佳选择,如果您在进行数据分析,模板3的Excel方法非常高效。