我有一个这样的数组:
var arr1 = ["a", "b", "c", "d"];
我如何随机化/打乱它?
我有一个这样的数组:
var arr1 = ["a", "b", "c", "d"];
我如何随机化/打乱它?
当前回答
社区表示arr.sort((a,b)=>0.5-Math.random())不是100%随机的!对我测试并建议不要使用此方法!
let arr = [1, 2, 3, 4, 5, 6]
arr.sort((a, b) => 0.5 - Math.random());
但我不确定。所以我写了一些代码来测试!。。。你也可以试试!如果你足够感兴趣!
让data_base=[];对于(设i=1;i<=100;i++){//将100次新的rendom arr推送到data_base!数据基础推送([1,2,3,4,5,6]排序((a,b)=>{return Math.random()-0.5;//使用了社区禁止的方法!:-)}));}//console.log(data_base);//如果你想看数据!让分析={};for(设i=1;i<=6;i++){analysis[i]=阵列(6).填充(0);}for(假设num=0;num<6;num++){for(设i=1;i<=100;i++){let plus=数据基[i-1][num];分析[`${num+1}`][plus-1]++;}}console.log(分析);//分析结果
在100个不同的随机阵列中。(我的分析结果)
{ player> 1 2 3 4 5 6
'1': [ 36, 12, 17, 16, 9, 10 ],
'2': [ 15, 36, 12, 18, 7, 12 ],
'3': [ 11, 8, 22, 19, 17, 23 ],
'4': [ 9, 14, 19, 18, 22, 18 ],
'5': [ 12, 19, 15, 18, 23, 13 ],
'6': [ 17, 11, 15, 11, 22, 24 ]
}
// player 1 got > 1(36 times),2(15 times),...,6(17 times)
// ...
// ...
// player 6 got > 1(10 times),2(12 times),...,6(24 times)
正如你所看到的,这不是那么随机!苏。。。不要使用此方法!如果你测试多次,你会看到玩家1获得了很多次(1号)!而球员6在大多数时候都获得了(第6名)!
其他回答
无序排列到位
function shuffleArr (array){
for (var i = array.length - 1; i > 0; i--) {
var rand = Math.floor(Math.random() * (i + 1));
[array[i], array[rand]] = [array[rand], array[i]]
}
}
ES6纯,迭代
const getShuffledArr = arr => {
const newArr = arr.slice()
for (let i = newArr.length - 1; i > 0; i--) {
const rand = Math.floor(Math.random() * (i + 1));
[newArr[i], newArr[rand]] = [newArr[rand], newArr[i]];
}
return newArr
};
可靠性和性能测试
本页上的一些解决方案不可靠(它们只是部分随机化了阵列)。其他解决方案的效率明显较低。使用testShuffleArrayFun(见下文),我们可以测试阵列洗牌功能的可靠性和性能。
function testShuffleArrayFun(getShuffledArrayFun){
const arr = [0,1,2,3,4,5,6,7,8,9]
var countArr = arr.map(el=>{
return arr.map(
el=> 0
)
}) // For each possible position in the shuffledArr and for
// each possible value, we'll create a counter.
const t0 = performance.now()
const n = 1000000
for (var i=0 ; i<n ; i++){
// We'll call getShuffledArrayFun n times.
// And for each iteration, we'll increment the counter.
var shuffledArr = getShuffledArrayFun(arr)
shuffledArr.forEach(
(value,key)=>{countArr[key][value]++}
)
}
const t1 = performance.now()
console.log(`Count Values in position`)
console.table(countArr)
const frequencyArr = countArr.map( positionArr => (
positionArr.map(
count => count/n
)
))
console.log("Frequency of value in position")
console.table(frequencyArr)
console.log(`total time: ${t1-t0}`)
}
其他解决方案
其他解决方案只是为了好玩。
ES6纯,递归
const getShuffledArr = arr => {
if (arr.length === 1) {return arr};
const rand = Math.floor(Math.random() * arr.length);
return [arr[rand], ...getShuffledArr(arr.filter((_, i) => i != rand))];
};
ES6纯使用array.map
function getShuffledArr (arr){
return [...arr].map( (_, i, arrCopy) => {
var rand = i + ( Math.floor( Math.random() * (arrCopy.length - i) ) );
[arrCopy[rand], arrCopy[i]] = [arrCopy[i], arrCopy[rand]]
return arrCopy[i]
})
}
ES6纯使用array.reduce
function getShuffledArr (arr){
return arr.reduce(
(newArr, _, i) => {
var rand = i + ( Math.floor( Math.random() * (newArr.length - i) ) );
[newArr[rand], newArr[i]] = [newArr[i], newArr[rand]]
return newArr
}, [...arr]
)
}
您可以通过以下方式轻松完成:
//阵列var fruits=[“香蕉”、“橙色”、“苹果”、“芒果”];//随机的,随机的fruits.sort(函数(a,b){return 0.5-Math.random()});//输出console.log(水果);
请参考JavaScript排序数组
这是一个Durstenfeld shuffle的JavaScript实现,这是Fisher Yates的优化版本:
/* Randomize array in-place using Durstenfeld shuffle algorithm */
function shuffleArray(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
它为每个原始数组元素选择一个随机元素,并将其排除在下一次抽奖中,就像从一副牌中随机选择一样。
这种巧妙的排除将拾取的元素与当前元素交换,然后从剩余元素中拾取下一个随机元素,向后循环以获得最佳效率,确保简化随机拾取(始终可以从0开始),从而跳过最终元素。
算法运行时间为O(n)。请注意,洗牌是在适当的位置完成的,因此如果您不想修改原始数组,请首先使用.sslice(0)复制它。
编辑:更新至ES6/ECMAScript 2015
新的ES6允许我们一次分配两个变量。当我们想要交换两个变量的值时,这特别方便,因为我们可以在一行代码中完成。下面是使用此功能的同一函数的简短形式。
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]];
}
}
警告不建议使用这种算法,因为它效率低且具有强烈的偏见;参见注释。它被留在这里供将来参考,因为这种想法并不罕见。
[1,2,3,4,5,6].sort( () => .5 - Math.random() );
这https://javascript.info/array-methods#shuffle-阵列教程直接解释了这些差异。
我认为还没有人给出一个可以在不扩展Array原型的情况下连接起来的解决方案(这是一个糟糕的做法)。使用稍微鲜为人知的reduce(),我们可以轻松地以允许串联的方式进行混洗:
var randomsquares = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle).map(n => n*n);
您可能希望传递第二个参数[],否则如果尝试在空数组上执行此操作,则会失败:
// Both work. The second one wouldn't have worked as the one above
var randomsquares = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle, []).map(n => n*n);
var randomsquares = [].reduce(shuffle, []).map(n => n*n);
让我们将shuffle定义为:
var shuffle = (rand, one, i, orig) => {
if (i !== 1) return rand; // Randomize it only once (arr.length > 1)
// You could use here other random algorithm if you wanted
for (let i = orig.length; i; i--) {
let j = Math.floor(Math.random() * i);
[orig[i - 1], orig[j]] = [orig[j], orig[i - 1]];
}
return orig;
}
您可以在JSFiddle或此处看到它的实际应用:
var shuffle=(all,one,i,orig)=>{如果(i!==1)返回全部;//你可以在这里使用其他随机算法for(设i=原始长度;i;i-){设j=数学地板(Math.random()*i);[原始[i-1],原始[j]]=[原始[j],原始[i-1]];}返回原点;}对于(变量i=0;i<5;i++){var randomarray=[1,2,3,4,5,6,7]。reduce(shuffle,[]);console.log(JSON.stringify(randomarray));}