js实现按权重取随机分布(生成多项分布算法)
问题描述
在使用Mock.js过程中发现随机取值可能不符合实际,例如:
如何实现按不同概率选取 员工80%,主管16%,领导4%
中间发现了多项分布算法及其部分资料,也和小猫nebulaqiqi探(mo)讨(yu)了下。
一种可能的方法(非最佳)
通过类似于北京摇号平台算法,复制多份实现多个编码对应一个有效号。虽然能实现功能,但是消耗大量的内存。算法复杂度为o(1),空间复杂度为o(n*weight)
const list = [{ v: '员工', p: 80 }, { v: '主管', p: 16 }, { v: '领导', p: 4 }]
let result = []
for (let i = 0; i < list.length; i++) {result = result.concat(new Array(list[i].p).fill(list[i].v))
}
return Random.pick(result)
多项分布方法
简单的使用二分法查找当前值所在的区域,得到最后区域的值。即算法复杂度为o(logn),空间复杂度为o(n),可参见R语言多项分布
预览效果
发现和理论值还是比较接近的,算法准确。
> n*p[1] ##巴萨获胜场数的理论值
[1] 3988.764
> n*p[2] ##巴萨打平场数的理论值
[1] 1966.292
> n*p[3] ##巴萨输皇马场数的理论值
[1] 4044.944
工具函数 algorithm.js
export function sortby(sort, desc) {const v = (sort ? 1 : 0) + (desc ? 2 : 0)switch (v) {case 0: return (a, b) => a - bcase 1: return (a, b) => a[sort] - b[sort]case 2: return (a, b) => b - acase 3: return (a, b) => b[sort] - a[sort]}
}/*** 二分法获取合适项** @export* @param {*} lst* @param {*} check_fit*/
export function dichotomy(lst, check_fit) {if (!lst || lst.length === 0) return nullconst lstLen = lst.length - 1let result = 0let nxtIndex = 0while (!check_fit(lst, result)) {nxtIndex = Math.floor((result + lstLen) / 2)if (result === lstLen + 1 || result === nxtIndex) return resultresult = nxtIndex}return result
}
算法核心 random.js
import { sortby, dichotomy } from './algorithm'
/*** 从指定集合中按权重选取** @export* @param {*} range* @param {*} weights*/
export function getRandomByWeight(range, weights) {const dict = getSortedByWeight(range, weights)if (!dict) return null// 区间设定return getRandomByWeightWithSortedList(dict)
}
const sortByWeight = sortby('w')
/*** 获取已排序的集合** @export* @param {*} range* @param {*} weights* @returns*/
export function getSortedByWeight(range, weights) {if (!range || !weights || range.length !== weights.length) return nullconst mapped = Object.keys(range).map((i) => ({ v: range[i], w: weights[i] }))// 排序列表,首项为权重为0const dict = [{ w: 0, v: null }].concat(mapped)const sorted_dict = dict.sort(sortByWeight)for (let i = 1; i < dict.length; i++) {const curW = dict[i - 1].wif (curW < 0) throw new RangeError(`${dict[i - 1].v} -> ${dict[i - 1].w} out of range`)dict[i].w = Number(dict[i].w) + Number(curW)}return sorted_dict
}
/*** 从已按权值排序的集合获取** @export* @param {*} dict* @returns*/
export function getRandomByWeightWithSortedList(dict) {// 总权重const total_weight = dict[dict.length - 1].w// 结果const val = Math.random() * total_weightconst result = dichotomy(dict, (lst, i) => lst[i].w < val && lst[i + 1].w > val)return dict[result + 1].v
}
调用方法
// 引入算法
import { getSortedByWeight, getRandomByWeightWithSortedList } from 'random'
// 初始化数据
const member_list = [{ v: '领导', w: 4 },{ v: '主管', w: 16 },{ v: '员工', w: 80 },
]
// 数据预处理
const member_list_list_sorted = getSortedByWeight(member_list.map(i => i.v), member_list.map(i => i.w))
// 输出按分布选中的结果
console.log(getRandomByWeightWithSortedList(member_list_list_sorted))
js实现按权重取随机分布(生成多项分布算法)相关推荐
- 生成特定分布随机数的方法:Python seed() 函数numpy scikit-learn随机数据生成
描述 seed() 方法改变随机数生成器的种子,可以在调用其他随机模块函数之前调用此函数.. 语法 以下是 seed() 方法的语法: import random random.seed ( [x] ...
- Auto.js Pro安卓免ROOT引流脚本开发系列教程28网易公开课(6)-取随机话术
APP_取随机话术() 返回值类型 说明 字符串型 话术内容 创建一个数组 将话术库的多条话术,存入数组 从数组里随机取一条内容 开发文档 在线文档 APP名称 网易公开课 APP版本 安卓客户端:v ...
- Matlab生成不同粒径和形状的二维离散颗粒随机分布
在岩土力学.泥沙运行.多相流颗粒物输送问题,常采用基于无网格法的光滑粒子法(SPH)或离散元法,而这些方法常需要对所研究问题建立初始的颗粒随机分布,在此以一个简单的案例加以说明,仅作抛砖引玉: 案例基 ...
- numpy,pytorch生成随机数,随机分布总结
在我们的平时的项目中,经常会用到生成随机数的方法.比如交叉验证中,随机采集的设置.在本文中将主要基于numpy常见的生成随机数方法和pytorch生成的随机数方法进行总结,并会分析随机种子对结果的影响 ...
- 游戏编程中的数学——随机数字生成(RNG)的黑暗秘密
大家好,你们能听到我讲话吗?这个演讲的内容是介绍RNG(随机数字生成)的一些黑暗秘密.如你在大屏幕上看到的,Squirrel已经介绍了一些RNG的基础概念.首先,我想详细讲解几点.他的演讲更偏重理论, ...
- 力扣随机数randX——透过现象看本质之二元独立随机分布
用randX 实现 randY(X < Y) 其中,randN表示等概生成[1,N]的数 从一个力扣上的例子来引入吧 470. 用 Rand7() 实现 Rand10() 最直观的想法是用ran ...
- 老慜的A5作业——p5.js 动态、周期、随机、面向对象
A5 "运动"主题的创意编程习作 终于到了这学期最后一个编程习作了,来看看最后这学期都憋出来什么玩意吧! A4pluse,上次作业中对蝴蝶的飞舞动作进行了优化,并且增加了一些环境细 ...
- 随机分布嵌入使短时高维序列可预测
[Randomly Distributed Embedding Making Short-term High-dimensional Data Predictable]的阅读与感悟. 随着大数据时代的 ...
- 高斯随机信号matlab,高斯随机信号生成初探.ppt
高斯随机信号生成初探 BPSK误码率仿真(n=30) QPSK误码率仿真(n=10) QPSK误码率仿真(n=30) 分析~3 在低SNR部分,三种方法产生的噪声对系统性能影响不大,而在高SNR部分, ...
最新文章
- sql查询每个学生的最高成绩mysql语句
- 扩有mysql的磁盘_为提高MySQL性能而在磁盘IO方面的设置
- MonoRail - 简介 [基础知识篇]
- xshell 6 连接debian系统拒绝了密码_Xshell中操作Linux的常用命令,你知道几个?
- python中字典的键是唯一的吗_在python3中反转字典中的键和值(值不唯一)
- python写入mysql数据库_python调用http接口,数据写入mysql数据库并下载录音文件
- Flink on Hive构建流批一体数仓
- 为什么博客园安卓端无法登陆,真服了
- JSK-337 汽水瓶【数学+模拟】
- vim 查找相同行 删除向同行
- VTD Trigger
- 云安全联盟CCSK认证获得CDM网络防御全球奖
- 苹果系统虚拟机无usb服务器,Mac上Vmware虚拟机无法识别USB Key怎么办?Mac虚拟机无法识别USB Key解决方法...
- 深度Deepin操作系统安装Docker
- openwrt-17.01.6 LEDE下载
- Minimal Area
- 8月20日 仿163邮箱中遇到的问题及解决(二)
- 【Java开发】 Mybatis-Plus 02:Mapper-CRUD+自动填充+乐观锁
- Git pull单个文件
- 中国的软件流氓行为何时了?搜狐输入法竟然自动下载并要求我安装浏览器!!...