我有一个这样的数组:

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

我如何随机化/打乱它?


当前回答

可理解的洗牌数组元素的方法设arr1=[“a”,“b”,“c”,“d”];函数洗牌(数组){let currentIndex=array.length;while(currentIndex!=0){let randomIndex=Math.floor(Math.random()*array.length);当前索引-=1;let temp=数组[currentIndex];array[currentIndex]=array[randomIndex];array[randomIndex]=临时;}返回数组;}设arr2=洗牌(arr1);arr2.forEach(元素=>console.log(元素));

其他回答

Fisher Yates的另一个实现,使用严格模式:

function shuffleArray(a) {
    "use strict";
    var i, t, j;
    for (i = a.length - 1; i > 0; i -= 1) {
        t = a[i];
        j = Math.floor(Math.random() * (i + 1));
        a[i] = a[j];
        a[j] = t;
    }
    return a;
}

这是最简单的一个,

function shuffle(array) {
  return array.sort(() => Math.random() - 0.5);
}

例如,您可以在此处查看

为了完整起见,除了Fischer Yates的Durstenfeld变体外,我还要指出Sattolo的算法,它只需要一个微小的变化,就会导致每个元素都发生变化。

function sattoloCycle(arr) {
   for (let i = arr.length - 1; 0 < i; i--) {
      const j = Math.floor(Math.random() * i);
      [arr[i], arr[j]] = [arr[j], arr[i]];
   }
   return arr
}

不同之处在于如何计算随机索引j,Math.random()*i与Math.random*(i+1)。

// Create a places array which holds the index for each item in the
// passed in array.
// 
// Then return a new array by randomly selecting items from the
// passed in array by referencing the places array item. Removing that
// places item each time though.
function shuffle(array) {
    let places = array.map((item, index) => index);
    return array.map((item, index, array) => {
      const random_index = Math.floor(Math.random() * places.length);
      const places_value = places[random_index];
      places.splice(random_index, 1);
      return array[places_value];
    })
}

无序排列到位

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