Как рандомизировать (перемешать) массив JavaScript?

У меня есть такой массив:

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

Как я могу рандомизировать / перемешать это?

74 ответа

Я не мог найти тот, который мне нравился. Вот решение, которое я придумал. Я не использовал слишком много бессмысленных переменных, так как сейчас я кодирую именно так.

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

Я надеюсь, что это поможет тем из вас, кто, возможно, не очень хорошо это понимает.

ИспользоватьforEachиMath.random()

       const arr = [
  { index: 0, value: "0" },
  { index: 1, value: "1" },
  { index: 2, value: "2" },
  { index: 3, value: "3" },
];
let shuffle = (arr) => {
  let set = new Set();
  while (set.size != arr.length) {
    let rand = Math.floor(Math.random() * arr.length);
    set.add(arr[rand]);
  }
  console.log(set);
};
shuffle(arr);

Я написал функцию случайного воспроизведения самостоятельно. Разница здесь в том, что он никогда не будет повторять значение (проверяет код для этого):

function shuffleArray(array) {
 var newArray = [];
 for (var i = 0; i < array.length; i++) {
     newArray.push(-1);
 }

 for (var j = 0; j < array.length; j++) {
    var id = Math.floor((Math.random() * array.length));
    while (newArray[id] !== -1) {
        id = Math.floor((Math.random() * array.length));
    }

    newArray.splice(id, 1, array[j]);
 }
 return newArray; }

Перемешать массив строк:

shuffle = (array) => {
  let counter = array.length, temp, index;
  while ( counter > 0 ) {
    index = Math.floor( Math.random() * counter );
    counter--;
    temp = array[ counter ];
    array[ counter ] = array[ index ];
    array[ index ] = temp;
  }
  return array;
 }

Перетасовка массива с использованием рекурсии JS.

Не лучшая реализация, но она рекурсивна и уважает неизменность.

const randomizer = (array, output = []) => {
    const arrayCopy = [...array];
    if (arrayCopy.length > 0) {    
        const idx = Math.floor(Math.random() * arrayCopy.length);
        const select = arrayCopy.splice(idx, 1);
        output.push(select[0]);
        randomizer(arrayCopy, output);
    }
    return output;
};

Быстрое и красивое решение (возможно, не самое эффективное)

const data = [1, 2, 3, 4, 5, 6];
const randomizedData = data
  .map(d => ({r: Math.random(), d}))
  .sort((a, b) => a.r - b.r)
  .map(d => d.d);

console.log(randomizedData);

Хочу поделиться одним из миллиона способов решения этой проблемы =)

function shuffleArray(array = ["banana", "ovo", "salsicha", "goiaba", "chocolate"]) {
const newArray = [];
let number = Math.floor(Math.random() * array.length);
let count = 1;
newArray.push(array[number]);

while (count < array.length) {
    const newNumber = Math.floor(Math.random() * array.length);
    if (!newArray.includes(array[newNumber])) {
        count++;
        number = newNumber;
        newArray.push(array[number]);
    }
}

return newArray;

}

здесь с простым циклом while

       function ShuffleColor(originalArray) {
        let shuffeledNumbers = [];
        while (shuffeledNumbers.length <= originalArray.length) {
            for (let _ of originalArray) {
                const randomNumb = Math.floor(Math.random() * originalArray.length);
                if (!shuffeledNumbers.includes(originalArray[randomNumb])) {
                    shuffeledNumbers.push(originalArray[randomNumb]);
                }
            }
            if (shuffeledNumbers.length === originalArray.length)
                break;
        }
        return shuffeledNumbers;
    }
const colors = [
    '#000000',
    '#2B8EAD',
    '#333333',
    '#6F98A8',
    '#BFBFBF',
    '#2F454E'
]
ShuffleColor(colors)
      //doesn change array
Array.prototype.shuffle = function () {
    let res = [];
    let copy = [...this];

    while (copy.length > 0) {
        let index = Math.floor(Math.random() * copy.length);
        res.push(copy[index]);
        copy.splice(index, 1);
    }

    return res;
};

let a=[1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(a.shuffle());

Используя метод сортировки и математический метод:

var arr =  ["HORSE", "TIGER", "DOG", "CAT"];
function shuffleArray(arr){
  return arr.sort( () => Math.floor(Math.random() * Math.floor(3)) - 1)  
}

// every time it gives random sequence
shuffleArr(arr);
// ["DOG", "CAT", "TIGER", "HORSE"]
// ["HORSE", "TIGER", "CAT", "DOG"]
// ["TIGER", "HORSE", "CAT", "DOG"]

$=(m)=>console.log(m);

//----add this method to Array class 
Array.prototype.shuffle=function(){
  return this.sort(()=>.5 - Math.random());
};

$([1,65,87,45,101,33,9].shuffle());
$([1,65,87,45,101,33,9].shuffle());
$([1,65,87,45,101,33,9].shuffle());
$([1,65,87,45,101,33,9].shuffle());
$([1,65,87,45,101,33,9].shuffle());

Сообщество говорит 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());

Но я не уверен. Итак, я пишу код для тестирования!... Вы также можете попробовать! Если вы достаточно заинтересованы!

let data_base = []; 
for (let i = 1; i <= 100; i++) { // push 100 time new rendom arr to data_base!
  data_base.push(
    [1, 2, 3, 4, 5, 6].sort((a, b) => {
      return  Math.random() - 0.5;     // used community banned method!  :-)      
    })
  );
} // console.log(data_base);  // if you want to see data!
let analysis = {};
for (let i = 1; i <= 6; i++) {
  analysis[i] = Array(6).fill(0);
}
for (let num = 0; num < 6; num++) {
  for (let i = 1; i <= 100; i++) {
    let plus = data_base[i - 1][num];
    analysis[`${num + 1}`][plus-1]++;
  }
}
console.log(analysis); // analysed result 

В 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) в большинстве случаев!

Функциональное решение с использованием Ramda.

const {map, compose, sortBy, prop} = require('ramda')

const shuffle = compose(
  map(prop('v')),
  sortBy(prop('i')),
  map(v => ({v, i: Math.random()}))
)

shuffle([1,2,3,4,5,6,7])
Другие вопросы по тегам