JavaScript生成指定范围无重复随机数:1000个对象的性能最优方案
性能最优的0-4范围不重复随机数对象生成方案
需求:生成1000个对象并存储到stack数组中,每个对象包含2个0-4范围内的不重复随机数,目标是找到速度性能最优的实现方法。
以下是两种实现方案及对应的基准测试得分(得分越高,性能越好):
方案一:直接随机选取并移除元素
基准测试得分:34664
const stack = []; for (let i = 0; i < 1000; i++) { const range = [0, 1, 2, 3, 4]; let r = Math.round(Math.random() * (range.length - 1)); let x = range[r]; range.splice(r, 1); let y = range[Math.round(Math.random() * (range.length - 1))]; stack.push({ x: x, y: y }); }
该方案每次循环创建完整的范围数组,通过Math.round()随机选取第一个元素后用splice()移除,再随机选取第二个元素。但splice()操作会修改数组并触发元素移位,累计1000次循环后会产生额外性能开销。
方案二:Fisher-Yates洗牌后取首尾元素
基准测试得分:41618
const stack = []; for (let i = 0; i < 1000; i++) { let range = [0, 1, 2, 3, 4]; shuffleArray(range); let x = range[0]; let y = range[range.length - 1]; stack.push({ x: x, y: y }); } function shuffleArray(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } }
该方案采用Fisher-Yates洗牌算法对范围数组进行原地打乱,直接取首尾元素作为两个不重复的随机数。Fisher-Yates洗牌仅做数组元素交换,无元素移位开销;同时Math.floor()比Math.round()更适配整数范围的随机选取(避免边界概率偏差的同时性能更稳定),因此整体性能优于方案一。
进一步优化建议
可以将基础范围数组的创建移到循环外,每次循环通过复制数组替代重新创建,减少数组初始化的重复开销:
const stack = []; const baseRange = [0, 1, 2, 3, 4]; for (let i = 0; i < 1000; i++) { let range = [...baseRange]; shuffleArray(range); stack.push({ x: range[0], y: range[4] }); } function shuffleArray(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } }
内容的提问来源于stack exchange,提问作者Tom Fan
相关产品推荐
相关产品推荐

