function shuffleArray(array) {
// 创建数组的副本,避免修改原始数组
const shuffledArray = [...array];
// Fisher-Yates 洗牌算法
for (let i = shuffledArray.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1)); // 随机索引 0 到 i
[shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]]; // 交换元素
}
return shuffledArray;
}
// 示例用法:
const originalArray = [1, 2, 3, 4, 5];
const shuffled = shuffleArray(originalArray);
console.log("Original array:", originalArray); // 输出原始数组,保持不变
console.log("Shuffled array:", shuffled); // 输出打乱后的数组
// 简化版 (如果可以直接修改原数组)
function shuffleArrayInPlace(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]];
}
}
// 示例用法
const myArray = [1, 2, 3, 4, 5];
shuffleArrayInPlace(myArray);
console.log("Shuffled array in place:", myArray);
// 使用sort方法的变种 (不推荐 - 分布不均匀)
// 虽然简洁,但由于sort的实现机制,这种方法的随机性不够理想,可能导致某些排列出现的概率更高。
function shuffleArraySort(array) {
return array.sort(() => Math.random() - 0.5);
}
解释:
-
shuffleArray(array)
: 这个版本创建了原数组的副本,并在副本上进行洗牌,保持原始数组不变。 这是推荐的做法,因为它避免了副作用。 -
shuffleArrayInPlace(array)
: 这个版本直接修改传入的数组。 如果你确定要修改原始数组,可以使用这个版本,它更节省内存。 -
shuffleArraySort(array)
: 这个版本使用sort
方法和一个随机比较函数。 虽然代码简洁,但它不推荐,因为sort
方法的随机比较函数会导致分布不均匀,某些排列出现的概率会更高,从而降低随机性。 -
Fisher-Yates 洗牌算法:
shuffleArray
和shuffleArrayInPlace
使用了 Fisher-Yates 洗牌算法 (也称为 Knuth 洗牌算法)。 这是公认的生成均匀随机排列的有效算法。 它的核心思想是从数组的最后一个元素开始,随机选择一个之前的元素与其交换位置。 然后,对倒数第二个元素重复此过程,依此类推,直到处理完第二个元素。
选择哪个版本取决于你的具体需求。 如果你需要保持原始数组不变,使用 shuffleArray
。 如果你可以修改原始数组并且想要节省内存,使用 shuffleArrayInPlace
。 避免使用 shuffleArraySort
,因为它不能保证真正的随机性。