我有一个这样的数组:
var arr1 = ["a", "b", "c", "d"];
我如何随机化/打乱它?
我有一个这样的数组:
var arr1 = ["a", "b", "c", "d"];
我如何随机化/打乱它?
当前回答
var shuffledArray = function(inpArr){
//inpArr - is input array
var arrRand = []; //this will give shuffled array
var arrTempInd = []; // to store shuffled indexes
var max = inpArr.length;
var min = 0;
var tempInd;
var i = 0;
do{
//generate random index between range
tempInd = Math.floor(Math.random() * (max - min));
//check if index is already available in array to avoid repetition
if(arrTempInd.indexOf(tempInd)<0){
//push character at random index
arrRand[i] = inpArr[tempInd];
//push random indexes
arrTempInd.push(tempInd);
i++;
}
}
// check if random array length is equal to input array length
while(arrTempInd.length < max){
return arrRand; // this will return shuffled Array
}
};
只需将数组传递给函数,然后得到经过洗牌的数组
其他回答
无序排列到位
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]
)
}
d3.js提供了Fisher–Yates shuffle的内置版本:
console.log(d3.shuffle([“a”,“b”,“c”,“d”]);<script src=“http://d3js.org/d3.v5.min.js“></script>
d3.洗牌(array[,lo[,hi]])<>使用Fisher–Yates混洗随机化指定阵列的顺序。
通过使用洗牌阵列模块,您可以洗牌您的阵列。这里有一个简单的代码。
var shuffle = require('shuffle-array'),
//collection = [1,2,3,4,5];
collection = ["a","b","c","d","e"];
shuffle(collection);
console.log(collection);
希望这有帮助。
NEW!
更短,可能更快的Fisher Yates洗牌算法
它使用while---按位到底数(最多10个十进制数字(32位))移除了不必要的封盖和其他东西
function fy(a,b,c,d){//array,placeholder,placeholder,placeholder
c=a.length;while(c)b=Math.random()*(--c+1)|0,d=a[c],a[c]=a[b],a[b]=d
}
脚本大小(以fy作为函数名):90字节
演示http://jsfiddle.net/vvpoma8w/
*可能在除chrome之外的所有浏览器上都更快。
如果您有任何问题,请提问。
EDIT
是的,它更快
性能:http://jsperf.com/fyshuffle
使用排名靠前的函数。
编辑计算过多(不需要--c+1),没有人注意到
更短(4字节)和更快(测试!)。
function fy(a,b,c,d){//array,placeholder,placeholder,placeholder
c=a.length;while(c)b=Math.random()*c--|0,d=a[c],a[c]=a[b],a[b]=d
}
在其他地方缓存var rnd=Math.random,然后使用rnd()也会稍微提高大数组的性能。
http://jsfiddle.net/vvpoma8w/2/
可读版本(使用原始版本。这会更慢,vars是无用的,像closures&“;”,代码本身也更短……也许读一下如何“缩小”Javascript代码,顺便说一句,你不能像上面那样用Javascript缩小器压缩以下代码。)
function fisherYates( array ){
var count = array.length,
randomnumber,
temp;
while( count ){
randomnumber = Math.random() * count-- | 0;
temp = array[count];
array[count] = array[randomnumber];
array[randomnumber] = temp
}
}
添加到@Laurens Holsts的答案。这是50%的压缩。
function shuffleArray(d) {
for (var c = d.length - 1; c > 0; c--) {
var b = Math.floor(Math.random() * (c + 1));
var a = d[c];
d[c] = d[b];
d[b] = a;
}
return d
};