问题描述

在使用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实现按权重取随机分布(生成多项分布算法)相关推荐

  1. 生成特定分布随机数的方法:Python seed() 函数numpy scikit-learn随机数据生成

    描述 seed() 方法改变随机数生成器的种子,可以在调用其他随机模块函数之前调用此函数.. 语法 以下是 seed() 方法的语法: import random random.seed ( [x] ...

  2. Auto.js Pro安卓免ROOT引流脚本开发系列教程28网易公开课(6)-取随机话术

    APP_取随机话术() 返回值类型 说明 字符串型 话术内容 创建一个数组 将话术库的多条话术,存入数组 从数组里随机取一条内容 开发文档 在线文档 APP名称 网易公开课 APP版本 安卓客户端:v ...

  3. Matlab生成不同粒径和形状的二维离散颗粒随机分布

    在岩土力学.泥沙运行.多相流颗粒物输送问题,常采用基于无网格法的光滑粒子法(SPH)或离散元法,而这些方法常需要对所研究问题建立初始的颗粒随机分布,在此以一个简单的案例加以说明,仅作抛砖引玉: 案例基 ...

  4. numpy,pytorch生成随机数,随机分布总结

    在我们的平时的项目中,经常会用到生成随机数的方法.比如交叉验证中,随机采集的设置.在本文中将主要基于numpy常见的生成随机数方法和pytorch生成的随机数方法进行总结,并会分析随机种子对结果的影响 ...

  5. 游戏编程中的数学——随机数字生成(RNG)的黑暗秘密

    大家好,你们能听到我讲话吗?这个演讲的内容是介绍RNG(随机数字生成)的一些黑暗秘密.如你在大屏幕上看到的,Squirrel已经介绍了一些RNG的基础概念.首先,我想详细讲解几点.他的演讲更偏重理论, ...

  6. 力扣随机数randX——透过现象看本质之二元独立随机分布

    用randX 实现 randY(X < Y) 其中,randN表示等概生成[1,N]的数 从一个力扣上的例子来引入吧 470. 用 Rand7() 实现 Rand10() 最直观的想法是用ran ...

  7. 老慜的A5作业——p5.js 动态、周期、随机、面向对象

    A5 "运动"主题的创意编程习作 终于到了这学期最后一个编程习作了,来看看最后这学期都憋出来什么玩意吧! A4pluse,上次作业中对蝴蝶的飞舞动作进行了优化,并且增加了一些环境细 ...

  8. 随机分布嵌入使短时高维序列可预测

    [Randomly Distributed Embedding Making Short-term High-dimensional Data Predictable]的阅读与感悟. 随着大数据时代的 ...

  9. 高斯随机信号matlab,高斯随机信号生成初探.ppt

    高斯随机信号生成初探 BPSK误码率仿真(n=30) QPSK误码率仿真(n=10) QPSK误码率仿真(n=30) 分析~3 在低SNR部分,三种方法产生的噪声对系统性能影响不大,而在高SNR部分, ...

最新文章

  1. sql查询每个学生的最高成绩mysql语句
  2. 扩有mysql的磁盘_为提高MySQL性能而在磁盘IO方面的设置
  3. MonoRail - 简介 [基础知识篇]
  4. xshell 6 连接debian系统拒绝了密码_Xshell中操作Linux的常用命令,你知道几个?
  5. python中字典的键是唯一的吗_在python3中反转字典中的键和值(值不唯一)
  6. python写入mysql数据库_python调用http接口,数据写入mysql数据库并下载录音文件
  7. Flink on Hive构建流批一体数仓
  8. 为什么博客园安卓端无法登陆,真服了
  9. JSK-337 汽水瓶【数学+模拟】
  10. vim 查找相同行 删除向同行
  11. VTD Trigger
  12. 云安全联盟CCSK认证获得CDM网络防御全球奖
  13. 苹果系统虚拟机无usb服务器,Mac上Vmware虚拟机无法识别USB Key怎么办?Mac虚拟机无法识别USB Key解决方法...
  14. 深度Deepin操作系统安装Docker
  15. openwrt-17.01.6 LEDE下载
  16. Minimal Area
  17. 8月20日 仿163邮箱中遇到的问题及解决(二)
  18. 【Java开发】 Mybatis-Plus 02:Mapper-CRUD+自动填充+乐观锁
  19. Git pull单个文件
  20. 中国的软件流氓行为何时了?搜狐输入法竟然自动下载并要求我安装浏览器!!...

热门文章

  1. hashCode是什么?
  2. 解决git cherry-pick 冲突
  3. 借用资质和违法分包,你了解吗
  4. Azure kubernetes(AKS)安装kubectl
  5. MSCI:无计划修改MSCI中国A股国际指数编制方法
  6. 车间生产设备管理有哪些问题?低代码来助力
  7. 原生html页面弹窗_javascript原生弹出框
  8. Python语言是解释性语言还是编译性语言?
  9. 一勤天下无难事,百忍堂中有太和
  10. 微信公众平台订阅号与服务号的区别