我有一个这样的数组:

var arr1 = ["a", "b", "c", "d"];

我如何随机化/打乱它?


当前回答

所有其他答案都基于Math.random(),它很快,但不适用于密码级别的随机化。

下面的代码使用了众所周知的Fisher Yates算法,同时利用Web Cryptography API实现了随机化的加密级别。

变量d=[1,2,3,4,5,6,7,8,9,10];函数洗牌(a){var x,t,r=新Uint32Array(1);对于(var i=0,c=a.length-1,m=a.length;i<c;i++,m-){crypto.getRandomValues(r);x=数学楼层(r/65536/65536*m)+i;t=a[i],a[i]=a[x],a[x]=t;}返回a;}console.log(shuffle(d));

其他回答

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
 }
}

使用生成器功能的ES6压缩代码*

这是通过从未屏蔽阵列的副本中随机移除项目,直到没有剩余项目。它使用新的ES6生成器功能。

设arr=[1,2,3,4,5,6,7]函数*洗牌(arr){arr=[…arr];而(arr.length)产生arr.splice(Math.random()*arr.length|0,1)[0]}console.log([…shuffle(arr)])

或者,使用ES6和拼接:

设arr=[1,2,3,4,5,6,7]let shuffled=arr.reduce(([a,b])=>(b.push(…a.splice(Math.random()*a.length |0,1)),[a,b]),[[…arr],[]])[1]console.log(混洗)

或者,ES6索引交换方法:

设arr=[1,2,3,4,5,6,7]let shuffled=arr.reduce((a,c,i,r,j)=>(j=数学随机()*(a.length-i)|0,[a[i],a[j]]=[a[j],a[i]],a),[…arr])console.log(混洗)

我找不到我喜欢的。这是我想出的解决方案。我没有使用太多无意义的变量,因为这是我现在的编码方式。

Array.prototype.shuffle = function() {
    for (let i in this) {
        if (this.hasOwnProperty(i)) {
            let index = Math.floor(Math.random() * i);
            [
                this[i],
                this[index]
            ] = [
                this[index],
                this[i]
            ];
        }
    }

    return this;
}

让arrayA=[“item1”、“item2”、“item3”、“Item 4”、“Items5”];Array.prototype.shuffle=函数(){为了(让我进来){如果(this.hasOwnProperty(i)){让index=Math.floor(Math.random()*i);[这个[i],此[索引]] = [该[索引],本[i]];}}返回此;}console.log(arrayA.shuffle());

我希望这能帮助那些可能不太理解这一点的人。

所有其他答案都基于Math.random(),它很快,但不适用于密码级别的随机化。

下面的代码使用了众所周知的Fisher Yates算法,同时利用Web Cryptography API实现了随机化的加密级别。

变量d=[1,2,3,4,5,6,7,8,9,10];函数洗牌(a){var x,t,r=新Uint32Array(1);对于(var i=0,c=a.length-1,m=a.length;i<c;i++,m-){crypto.getRandomValues(r);x=数学楼层(r/65536/65536*m)+i;t=a[i],a[i]=a[x],a[x]=t;}返回a;}console.log(shuffle(d));

编辑:此答案不正确

参见评论和https://stackoverflow.com/a/18650169/28234.这里留作参考,因为这种想法并不罕见。


对于小型阵列,一个非常简单的方法就是:

const someArray = [1, 2, 3, 4, 5];

someArray.sort(() => Math.random() - 0.5);

它可能效率不高,但对于小型阵列来说,这很好。这里有一个例子,你可以看到它有多随机(或不随机),以及它是否适合你的用例。

const resultsEl=document.querySelector(“#results”);const buttonEl=document.querySelector(“#trigger”);常量生成器数组和随机化=()=>{常量someArray=[0,1,2,3,4,5,6,7,8,9];someArray.sort(()=>Math.random()-0.5);return someArray;};const renderResultsToDom=(结果,el)=>{el.innerHTML=results.join(“”);};buttonEl.addEventListener('click',()=>renderResultsToDom(generateArray AndRandomize(),resultsEl));<h1>随机化</h1><button id=“trigger”>生成</button><p id=“results”>0 1 2 3 4 5 6 7 8 9</p>