JS如何从列表抽取3个随机元素并按指定概率控制三者相同
代码调整实现方案
核心逻辑
你的需求是主动控制3个抽取结果全相同的概率,由于1500个元素的场景下,自然随机抽取出3个相同元素的概率仅约为0.00004%,远低于你需要的2%~30%档位区间,因此我们可以通过主动判定概率的方式实现控制:
- 先根据用户得票数匹配到你预设的概率档位,得到三者全相同的目标概率值(如2%对应0.02,30%对应0.3)
- 生成0~1的随机数,若随机数小于等于目标概率值,直接返回3个相同的随机元素
- 若未命中概率区间,保持原有随机抽取逻辑即可,自然重复的概率极低,几乎不会影响整体统计结果
调整后可直接使用的代码
// 你的 cosmetics 列表 let cosmetics = ["item1", "item2", "etc..."]; /** * 根据用户得票数匹配三者全相同的概率档位,可自行修改映射规则 * @param {number} userVotes 用户得票数 * @returns {number} 0~1之间的概率值 */ function getSameProbability(userVotes) { // 示例映射规则,可根据你的业务需求调整 if (userVotes >= 1000) return 0.3; // 30% 档位 if (userVotes >= 800) return 0.25; // 25% 档位 if (userVotes >= 600) return 0.2; // 20% 档位 if (userVotes >= 400) return 0.15; // 15% 档位 if (userVotes >= 200) return 0.1; // 10% 档位 if (userVotes >= 100) return 0.05; // 5% 档位 return 0.02; // 最低 2% 档位 } /** * 抽取3个元素,支持控制三者全相同的概率 * @param {number} userVotes 用户得票数 * @returns {Array} 抽取结果数组 */ function drawThreeItems(userVotes) { const targetSameProb = getSameProbability(userVotes); const items = []; // 命中三者全相同的概率区间 if (Math.random() <= targetSameProb) { const selectedItem = cosmetics[Math.floor(Math.random() * cosmetics.length)]; items.push(selectedItem, selectedItem, selectedItem); return items; } // 未命中,执行正常随机抽取逻辑 for (let i = 0; i < 3; i++) { items.push(cosmetics[Math.floor(Math.random() * cosmetics.length)]); } // 可选:如果需要严格保证非触发场景下绝对不会出现三者相同,可取消下面代码的注释 // while (items[0] === items[1] && items[1] === items[2]) { // items.length = 0; // for (let i = 0; i < 3; i++) { // items.push(cosmetics[Math.floor(Math.random() * cosmetics.length)]); // } // } return items; } // 调用示例:传入对应用户的得票数即可得到结果 // const drawResult = drawThreeItems(用户实际得票数);
使用说明
- 只需修改
getSameProbability函数内的映射规则,适配你得票数和概率档位的对应关系即可 - 实现逻辑性能损耗极低,完全适配discord.js指令的调用场景
注意:概率档位需要转换为0~1之间的小数传入,例如2%要写为0.02,不要直接传入整数2
内容的提问来源于stack exchange,提问作者Jose Manuel
相关产品推荐
相关产品推荐

