如何打乱 Javascript 数组以确保每个索引都位于新数组中的新位置?
How do I shuffle a Javascript Array ensuring each Index is in a new position in the new Array?
我有一个对象数组,就像这样。
var usersGoing = [
{ user: 0 },
{ user: 1 },
{ user: 2 },
{ user: 3 },
{ user: 4 }
];
我需要打乱这个数组,以便没有对象保留在与实例化时相同的索引中,如下所示:
[
{ user: 3 },
{ user: 2 },
{ user: 4 },
{ user: 0 },
{ user: 1 }
]
生成的数组必须以这种方式排序,因为每个用户对象都将分配给不同的用户对象。
我尝试了几种不同的排序算法,包括 Fisher-Yates,并且我尝试使用 Underscore.js' _.shuffle(),以及 Kirupa Shuffling an Array in JavaScript 的这个变体:
function shuffleFY(input) {
for (var i = input.length-1; i >=0; i--) {
var randomIndex = Math.floor(Math.random()*(i+1));
var itemAtIndex = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
return input;
}
我试过的都没有用。有帮助吗?
更新:我在下面将答案标记为正确,因为正确遵循了 Sattolo 循环的关键点。此外,这不是 Shuffles Random Numbers with no repetition in Javascript/PHP 的重复项,因为此问题对结果数组有额外要求,不仅不包含重复项,而且不能在相同的初始索引位置包含项目。
对于每个位置,随机选择一个位置较高的索引并将两者交换。
每个对象要么在自己的位置并换出并锁定其原始位置,要么在其位置准备好更换时换到较低的位置并锁定到位。
当您到达倒数第二个位置时,您将保证换出最后一个位置(它可能与原来的值相同,也可能不同),您就完成了。最终位置无事可做。
1 2 3 4 5 - 原始值
3 2 1 4 5
3 1 2 4 5
3 1 4 2 5
3 1 4 5 2
试试这个 Fisher-Yates-Durstenfeld shuffle:
var usersGoing = [
{ user: 0 },
{ user: 1 },
{ user: 2 },
{ user: 3 },
{ user: 4 }
];
shuffle(usersGoing);
function shuffle(sourceArray) {
for (var n = 0; n < sourceArray.length - 1; n++) {
var k = n + Math.floor(Math.random() * (sourceArray.length - n));
var temp = sourceArray[k];
sourceArray[k] = sourceArray[n];
sourceArray[n] = temp;
}
}
console.log(usersGoing);
您在 Python 中使用 Sattolo 的算法发布了 link:
from random import randrange
def sattoloCycle(items):
i = len(items)
while i > 1:
i = i - 1
j = randrange(i) # 0 <= j <= i-1
items[j], items[i] = items[i], items[j]
return
这里翻译成JavaScript:
function sattoloCycle(items) {
for(var i = items.length; i-- > 1; ) {
var j = Math.floor(Math.random() * i);
var tmp = items[i];
items[i] = items[j];
items[j] = tmp;
}
}
有点过时的答案,可能您的软件现在已经完成、打包和销售,但有更好的方法来实现这一点...
const arr = [1,2,3,4,5,6,7,8,9];
const sfl = arr.sort( () => { Math.random() - .5 } );
// sfl == [2,9,5,1,3,6,...]
@xaxxon 删掉的答案是对的。就“洗牌”一词而言,这不是一个有意义的请求。洗牌的时候不能设置这样的限制条件,因为洗牌涉及到随机性。对于你想要的,只需旋转阵列就可以了。如果您现在对轮换不满意,您必须解释原因...
我有一个对象数组,就像这样。
var usersGoing = [
{ user: 0 },
{ user: 1 },
{ user: 2 },
{ user: 3 },
{ user: 4 }
];
我需要打乱这个数组,以便没有对象保留在与实例化时相同的索引中,如下所示:
[
{ user: 3 },
{ user: 2 },
{ user: 4 },
{ user: 0 },
{ user: 1 }
]
生成的数组必须以这种方式排序,因为每个用户对象都将分配给不同的用户对象。
我尝试了几种不同的排序算法,包括 Fisher-Yates,并且我尝试使用 Underscore.js' _.shuffle(),以及 Kirupa Shuffling an Array in JavaScript 的这个变体:
function shuffleFY(input) {
for (var i = input.length-1; i >=0; i--) {
var randomIndex = Math.floor(Math.random()*(i+1));
var itemAtIndex = input[randomIndex];
input[randomIndex] = input[i];
input[i] = itemAtIndex;
}
return input;
}
我试过的都没有用。有帮助吗?
更新:我在下面将答案标记为正确,因为正确遵循了 Sattolo 循环的关键点。此外,这不是 Shuffles Random Numbers with no repetition in Javascript/PHP 的重复项,因为此问题对结果数组有额外要求,不仅不包含重复项,而且不能在相同的初始索引位置包含项目。
对于每个位置,随机选择一个位置较高的索引并将两者交换。
每个对象要么在自己的位置并换出并锁定其原始位置,要么在其位置准备好更换时换到较低的位置并锁定到位。
当您到达倒数第二个位置时,您将保证换出最后一个位置(它可能与原来的值相同,也可能不同),您就完成了。最终位置无事可做。
1 2 3 4 5 - 原始值
3 2 1 4 5
3 1 2 4 5
3 1 4 2 5
3 1 4 5 2
试试这个 Fisher-Yates-Durstenfeld shuffle:
var usersGoing = [
{ user: 0 },
{ user: 1 },
{ user: 2 },
{ user: 3 },
{ user: 4 }
];
shuffle(usersGoing);
function shuffle(sourceArray) {
for (var n = 0; n < sourceArray.length - 1; n++) {
var k = n + Math.floor(Math.random() * (sourceArray.length - n));
var temp = sourceArray[k];
sourceArray[k] = sourceArray[n];
sourceArray[n] = temp;
}
}
console.log(usersGoing);
您在 Python 中使用 Sattolo 的算法发布了 link:
from random import randrange
def sattoloCycle(items):
i = len(items)
while i > 1:
i = i - 1
j = randrange(i) # 0 <= j <= i-1
items[j], items[i] = items[i], items[j]
return
这里翻译成JavaScript:
function sattoloCycle(items) {
for(var i = items.length; i-- > 1; ) {
var j = Math.floor(Math.random() * i);
var tmp = items[i];
items[i] = items[j];
items[j] = tmp;
}
}
有点过时的答案,可能您的软件现在已经完成、打包和销售,但有更好的方法来实现这一点...
const arr = [1,2,3,4,5,6,7,8,9];
const sfl = arr.sort( () => { Math.random() - .5 } );
// sfl == [2,9,5,1,3,6,...]
@xaxxon 删掉的答案是对的。就“洗牌”一词而言,这不是一个有意义的请求。洗牌的时候不能设置这样的限制条件,因为洗牌涉及到随机性。对于你想要的,只需旋转阵列就可以了。如果您现在对轮换不满意,您必须解释原因...