如何随机打乱一个 JavaScript 数组?
如何随机打乱一个 JavaScript 数组?
技术背景
在 JavaScript 开发中,经常会遇到需要随机打乱数组元素顺序的需求,比如游戏中的洗牌、随机展示数据等。而实现这一需求的关键在于选择合适的随机打乱算法。
实现步骤
Fisher–Yates(aka Knuth)洗牌算法
这是一种被广泛认可的无偏洗牌算法。具体步骤如下:
- 从数组的最后一个元素开始,向前遍历。
- 对于每个位置
i
,随机选择一个从0
到i
之间的索引j
。 - 交换位置
i
和j
的元素。
代码示例
1 |
|
其他实现方式
使用 map
和 sort
1 |
|
使用 lodash
库
1 |
|
最佳实践
- 对于大多数情况,推荐使用 Fisher–Yates 洗牌算法,因为它的时间复杂度为 $O(n)$,且能保证每个排列的概率相等。
- 如果需要对数组进行多次打乱操作,并且数组长度较大,建议使用 Fisher–Yates 算法的优化版本,避免不必要的元素交换。
- 如果对随机性要求不高,且数组长度较小,可以使用简单的
sort
方法结合Math.random()
来实现,但要注意这种方法存在一定的偏差。
常见问题
使用 sort
方法打乱数组存在偏差
使用 array.sort(() => Math.random() - 0.5)
这种方式打乱数组时,由于 sort
方法的实现机制,可能会导致某些排列的概率更高,从而产生偏差。因此,不建议在对随机性要求较高的场景中使用这种方法。
避免修改原数组
如果不希望修改原数组,可以在打乱之前先复制一份数组,然后对复制后的数组进行操作。例如:
1 |
|
性能问题
在处理大规模数组时,一些算法可能会导致性能问题。例如,使用 splice
方法在循环中删除元素会使时间复杂度增加,建议使用更高效的算法,如 Fisher–Yates 算法。
如何随机打乱一个 JavaScript 数组?
https://119291.xyz/posts/how-to-randomize-a-javascript-array/