Как рандомизировать (перемешать) массив JavaScript? - PullRequest
1065 голосов
/ 16 марта 2010

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

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

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

Ответы [ 50 ]

15 голосов
/ 20 декабря 2015

С ES2015 вы можете использовать это:

Array.prototype.shuffle = function() {
  let m = this.length, i;
  while (m) {
    i = (Math.random() * m--) >>> 0;
    [this[m], this[i]] = [this[i], this[m]]
  }
  return this;
}

Использование:

[1, 2, 3, 4, 5, 6, 7].shuffle();
14 голосов
/ 09 августа 2013
var shuffle = function(array) {
   temp = [];
   originalLength = array.length;
   for (var i = 0; i < originalLength; i++) {
     temp.push(array.splice(Math.floor(Math.random()*array.length),1));
   }
   return temp;
};
13 голосов
/ 25 июня 2015

Я обнаружил, что этот вариант висит в ответах "удалено автором" на дубликат этого вопроса. В отличие от некоторых других ответов, которые уже имеют много голосов, это:

  1. На самом деле случайный
  2. Не на месте (отсюда и название shuffled, а не shuffle)
  3. Не представлен здесь с несколькими вариантами

Вот jsfiddle, показывающий его использование .

Array.prototype.shuffled = function() {
  return this.map(function(n){ return [Math.random(), n] })
             .sort().map(function(n){ return n[1] });
}
10 голосов
/ 20 июня 2018

Вы можете сделать это легко с:

// array
var fruits = ["Banana", "Orange", "Apple", "Mango"];
// random
fruits.sort(function(a, b){return 0.5 - Math.random()});
// out
console.log(fruits);

Пожалуйста, укажите на Массивы сортировки JavaScript

8 голосов
/ 26 марта 2014

Рекурсивное решение:

function shuffle(a,b){
    return a.length==0?b:function(c){
        return shuffle(a,(b||[]).concat(c));
    }(a.splice(Math.floor(Math.random()*a.length),1));
};
7 голосов
/ 14 января 2018

функция перемешивания, которая не меняет исходный массив

Обновление : здесь я предлагаю относительно простой (не с точки зрения сложность ) и короткий алгоритм, который будет просто хорошо с небольшими массивами, но это определенно будет стоить намного больше, чем классический Durstenfeld алгоритм, когда вы имеете дело с огромными массивами. Вы можете найти Durstenfeld в одном из лучших ответов на этот вопрос.

Оригинальный ответ:

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

function shuffle(array) {
  var result = [], source = array.concat([]);

  while (source.length) {
    let index = Math.floor(Math.random() * source.length);
    result.push(source[index]);
    source.splice(index, 1);
  }

  return result;
}

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

И если вы действительно хотите, чтобы это было коротко, вот как далеко я мог бы получить:

function shuffle(array) {
  var result = [], source = array.concat([]);

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

  return result;
}
7 голосов
/ 04 августа 2015

Фишер-Йейтс перемешать в javascript. Я публикую это здесь, поскольку использование двух служебных функций (swap и randInt) поясняет алгоритм по сравнению с другими ответами здесь.

function swap(arr, i, j) { 
  // swaps two elements of an array in place
  var temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}
function randInt(max) { 
  // returns random integer between 0 and max-1 inclusive.
  return Math.floor(Math.random()*max);
}
function shuffle(arr) {
  // For each slot in the array (starting at the end), 
  // pick an element randomly from the unplaced elements and
  // place it in the slot, exchanging places with the 
  // element in the slot. 
  for(var slot = arr.length - 1; slot > 0; slot--){
    var element = randInt(slot+1);
    swap(arr, element, slot);
  }
}
7 голосов
/ 29 марта 2015

Прежде всего, посмотрите здесь для отличного визуального сравнения различных методов сортировки в javascript.

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

function shuffle(array) {
  var random = array.map(Math.random);
  array.sort(function(a, b) {
    return random[array.indexOf(a)] - random[array.indexOf(b)];
  });
}

Редактировать : как указано @gregers, функция сравнения вызывается со значениями, а не с индексами, поэтому вам нужно использовать indexOf. Обратите внимание, что это изменение делает код менее подходящим для больших массивов, так как indexOf выполняется за O (n) времени.

6 голосов
/ 20 марта 2019
function shuffle(array) {
  array.sort(() => Math.random() - 0.5);
}

let arr = [1, 2, 3];
shuffle(arr);
alert(arr);

https://javascript.info/task/shuffle

5 голосов
/ 21 октября 2013

еще одна реализация Фишера-Йейтса, использующая строгий режим:

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