悠悠楠杉
实用技巧:JavaScript实现数组随机排序的5种方法
实用技巧:JavaScript实现数组随机排序的5种方法
在日常开发中,数组随机排序是个常见需求。本文将介绍5种实现方式,并分析它们的优劣。
一、Fisher-Yates洗牌算法(推荐)
javascript
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]];
}
return array;
}
这是最经典的算法,时间复杂度O(n),能保证每个元素出现在每个位置的概率相同。
二、sort()结合随机数
javascript
function randomSort(arr) {
return arr.sort(() => Math.random() - 0.5);
}
虽然写法简洁,但实际效果并不完全随机。Chrome等浏览器使用的排序算法会导致元素分布不均匀。
三、ES6展开运算符实现
javascript
const shuffle = arr => [...arr].sort(() => Math.random() - 0.5);
这种写法不会改变原数组,适合函数式编程场景,但仍存在sort方法相同的随机性问题。
四、递归实现方案
javascript
function recursiveShuffle(arr, result = []) {
if (!arr.length) return result;
const randomIndex = Math.floor(Math.random() * arr.length);
result.push(arr.splice(randomIndex, 1)[0]);
return recursiveShuffle(arr, result);
}
递归写法展示了另一种思路,但需要注意递归深度限制。
五、使用Lodash库
javascript
_.shuffle([1, 2, 3, 4]);
对于已使用Lodash的项目,这是最便捷的方案。内部实现也是基于Fisher-Yates算法。
性能对比测试
| 方法 | 10万数据耗时 | 随机性 |
|--------------------|-------------|-------|
| Fisher-Yates | 15ms | 完美 |
| sort随机法 | 120ms | 一般 |
| Lodash实现 | 18ms | 完美 |
| 递归实现 | 堆栈溢出 | 良好 |
实际应用场景
- 音乐播放列表:需要真正的随机播放
- 抽奖系统:必须保证公平性
- 推荐算法:避免出现模式化推荐
- 游戏开发:卡牌洗牌、敌人出场顺序
注意事项
- 密码学场景应使用
crypto.getRandomValues()
- 移动端注意性能影响
- 大量数据时避免递归实现
掌握这些方法后,相信你能根据具体需求选择最适合的方案。好的随机算法就像魔术师洗牌,既要看起来随机,又要保证公平。