如何在不移动 FALSY 元素的情况下洗牌数组?
How to shuffle an array without moving FALSY elements?
这是我的尝试;稍作修改的 Fisher-Yates 算法。不过我不确定如何确保它是随机的。
const shuffleWithoutMovingFalsies = array => {
const newArray = [...array];
const getRandomValue = (i, N) => ~~(Math.random() * (N - i) + i);
newArray.forEach((elem, i, arr, j = getRandomValue(i, arr.length)) => arr[i] && arr[j] && ([arr[i], arr[j]] = [arr[j], arr[i]]));
return newArray;
}
const array = [1, 2, null, 3, null, null, 4, 5, 6, null];
const shuffledArray = shuffleWithoutMovingFalsies(array);
console.log(shuffledArray);
我所做的只是添加 arr[i] && arr[j] &&
作为检查,以确保要交换的两个元素都不是 falsy
。
这使它无法公平洗牌。例如,对于数组 [1, null, 2]
,1
应该有 50% 的机会保持原状,并有 50% 的机会与 2
交换,但分裂是 ⅔–⅓。
只要辅助记忆不是问题,我建议提取元素,洗牌,然后放回去以简单起见:
const shuffle = arr => {
for (let i = 0; i < arr.length - 1; i++) {
const j = i + Math.floor(Math.random() * (arr.length - i));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
};
const shuffleTruthy = arr => {
const truthy = arr.filter(Boolean);
shuffle(truthy);
let j = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i]) {
arr[i] = truthy[j++];
}
}
};
这是我的尝试;稍作修改的 Fisher-Yates 算法。不过我不确定如何确保它是随机的。
const shuffleWithoutMovingFalsies = array => {
const newArray = [...array];
const getRandomValue = (i, N) => ~~(Math.random() * (N - i) + i);
newArray.forEach((elem, i, arr, j = getRandomValue(i, arr.length)) => arr[i] && arr[j] && ([arr[i], arr[j]] = [arr[j], arr[i]]));
return newArray;
}
const array = [1, 2, null, 3, null, null, 4, 5, 6, null];
const shuffledArray = shuffleWithoutMovingFalsies(array);
console.log(shuffledArray);
我所做的只是添加 arr[i] && arr[j] &&
作为检查,以确保要交换的两个元素都不是 falsy
。
这使它无法公平洗牌。例如,对于数组 [1, null, 2]
,1
应该有 50% 的机会保持原状,并有 50% 的机会与 2
交换,但分裂是 ⅔–⅓。
只要辅助记忆不是问题,我建议提取元素,洗牌,然后放回去以简单起见:
const shuffle = arr => {
for (let i = 0; i < arr.length - 1; i++) {
const j = i + Math.floor(Math.random() * (arr.length - i));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
};
const shuffleTruthy = arr => {
const truthy = arr.filter(Boolean);
shuffle(truthy);
let j = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i]) {
arr[i] = truthy[j++];
}
}
};