
本文介绍一种基于预设百分比权重,将物品数组精确、可复用地分配给多个对象的算法实现,适用于负载均衡、资源调度等场景。
本文介绍一种基于预设百分比权重,将物品数组精确、可复用地分配给多个对象的算法实现,适用于负载均衡、资源调度等场景。
在实际开发中,我们常需根据权重(如分配百分比)将一批离散资源(如任务、数据项、用户请求)分发到多个处理单元(如服务实例、存储桶、业务模块)。关键要求是:分配结果必须严格符合各单元的百分比配置,且整体不遗漏、不重复、可预测。
以下是一个简洁、健壮的实现方案:
✅ 核心思路
- 归一化处理:确保所有对象的 allocationPercentage 总和为 100(或自动校准);
- 整数截断 + 渐进累积:使用 Math.floor() 计算每个对象应得的基础项数,通过游标(cursor)顺序切片,避免浮点误差累积;
- 余量兜底(可选增强):基础版本可能因向下取整导致少量物品未分配(如 5 项 × 20% = 1.0 → 1,但 3×20%=0.6→0),若需 100% 分配,可在最后将剩余项按权重优先级补入(见注意事项)。
? 示例代码(基础版)
const items = ["item1", "item2", "item3", "item4", "item5"];
const obj1 = { id: 1, allocationPercentage: 40, items: [] };
const obj2 = { id: 2, allocationPercentage: 20, items: [] };
const obj3 = { id: 3, allocationPercentage: 40, items: [] };
const objs = [obj1, obj2, obj3];
let cursor = 0;
for (const obj of objs) {
const count = Math.floor((obj.allocationPercentage / 100) * items.length);
obj.items.push(...items.slice(cursor, cursor + count)); // 注意:使用 ... 展开而非 push([])!
cursor += count;
}
console.log(objs);
// 输出:
// [
// { id: 1, allocationPercentage: 40, items: ["item1", "item2"] },
// { id: 2, allocationPercentage: 20, items: ["item3"] },
// { id: 3, allocationPercentage: 40, items: ["item4", "item5"] }
// ]
⚠️ 重要修正:原答案中 obj.items.push(itemsToAdd) 会将数组作为子数组嵌套,正确写法应为 obj.items.push(...itemsToAdd) 或 obj.items = obj.items.concat(itemsToAdd),否则结构不符合预期。
? 注意事项与进阶建议
- 百分比校验:生产环境建议先验证 objs.reduce((sum, o) => sum + o.allocationPercentage, 0) === 100,否则需归一化或抛出警告;
- 小数量偏差处理:当 items.length 较小时(如 ≤10),Math.floor 可能导致某些低权重对象分不到任何项。若业务要求“至少分 1 项”,可改用 Math.round 并配合余量重分配;
- 动态扩展支持:该算法天然支持对象增删——只需重新运行分配逻辑即可;
- 性能考量:时间复杂度 O(n + m),n 为物品数,m 为对象数,适用于千级以内规模;超大规模建议改用流式分发或 Web Worker。
通过此方法,你可构建稳定、透明、易测试的加权分配系统,无论是模拟 A/B 测试流量分流,还是实现数据库分片路由,均能提供可靠的基础能力。











