web-dev-qa-db-fra.com

Comment aléatoire (shuffle) un tableau JavaScript?

J'ai un tableau comme celui-ci:

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

Comment puis-je randomiser/mélanger?

979
Click Upvote

L'algorithme de mélange impartial de facto est le Fisher-Yates (aka Knuth) Shuffle.

Voir https://github.com/coolaj86/knuth-shuffle

Vous pouvez voir une grande visualisation ici (et le message original lié à cela )

function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

// Used like so
var arr = [2, 11, 37, 42];
arr = shuffle(arr);
console.log(arr);

Quelques informations supplémentaires sur l’algorithme utilisé.

1222
ChristopheD

Voici une implémentation JavaScript de Durstenfeld shuffle , une version optimisée par ordinateur de Fisher-Yates:

/**
 * Randomize array element order in-place.
 * Using Durstenfeld shuffle algorithm.
 */
function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

L'algorithme de Fisher-Yates fonctionne en choisissant un élément aléatoire pour chaque élément de tableau d'origine, puis en l'excluant du prochain tirage. Tout comme choisir au hasard dans un jeu de cartes.

Cette exclusion est faite de manière intelligente (inventée par Durstenfeld pour être utilisée par des ordinateurs) en échangeant l’élément sélectionné avec l’élément actuel, puis en sélectionnant l’élément aléatoire suivant dans le reste. Pour une efficacité optimale, la boucle fonctionne à l'envers, ce qui simplifie la sélection aléatoire (elle peut toujours commencer à 0) et ignore le dernier élément car il n'y a plus d'autre choix.

Le temps d'exécution de cet algorithme est O (n). Notez que le shuffle est fait sur place. Donc, si vous ne voulez pas modifier le tableau d'origine, faites-en une copie d'abord avec .slice(0).

Mise à jour vers ES6/ECMAScript 2015

La nouvelle ES6 nous permet d’attribuer deux variables à la fois. Ceci est particulièrement utile lorsque nous voulons échanger les valeurs de deux variables, car nous pouvons le faire dans une ligne de code. Voici une forme plus courte de la même fonction, en utilisant cette fonctionnalité. 

function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}
564
Laurens Holst

[communauté edit: Cette réponse est incorrecte; voir les commentaires. Il est laissé ici pour référence future car l’idée n’est pas si rare.]

[1,2,3,4,5,6].sort(function() {
  return .5 - Math.random();
});
98
deadrunk

On pourrait (ou devrait) l’utiliser comme prototype de Array:

De ChristopheR:

Array.prototype.shuffle = function() {
  var i = this.length, j, temp;
  if ( i == 0 ) return this;
  while ( --i ) {
     j = Math.floor( Math.random() * ( i + 1 ) );
     temp = this[i];
     this[i] = this[j];
     this[j] = temp;
  }
  return this;
}
68
con

Utilisez la bibliothèque underscore.js. La méthode _.shuffle() est agréable pour ce cas . Voici un exemple avec la méthode:

var _ = require("underscore");

var arr = [1,2,3,4,5,6];
// Testing _.shuffle
var testShuffle = function () {
  var indexOne = 0;
    var stObj = {
      '0': 0,
      '1': 1,
      '2': 2,
      '3': 3,
      '4': 4,
      '5': 5
    };
    for (var i = 0; i < 1000; i++) {
      arr = _.shuffle(arr);
      indexOne = _.indexOf(arr, 1);
      stObj[indexOne] ++;
    }
    console.log(stObj);
};
testShuffle();
56
vn_grv

NOUVEAU!

Plus court et probablement * plus rapide algorithme de lecture aléatoire Fisher-Yates

  1. il utilise pendant que ---
  2. bit à étage (nombres jusqu'à 10 chiffres décimaux (32 bits))
  3. suppression des fermetures inutiles et autres

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
}

taille du script (avec fy comme nom de la fonction): 90 octets 

D&EACUTE;MOhttp://jsfiddle.net/vvpoma8w/

* plus rapide probablement sur tous les navigateurs sauf chrome.

Si vous avez des questions, vous avez juste à me les poser.

MODIFIER

oui c'est plus rapide

PERFORMANCE: _ ​​ http://jsperf.com/fyshuffle

en utilisant les fonctions les plus votées.

EDIT Il y avait un calcul en excès (pas besoin de --c + 1) et personne n'a remarqué

plus court (4 octets) et plus rapide (testez-le!).

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
}

Mettre en cache quelque chose d'autre var rnd=Math.random et ensuite utiliser rnd() augmenterait également légèrement les performances sur les grands tableaux.

http://jsfiddle.net/vvpoma8w/2/

Version lisible (utilisez la version originale. C'est plus lent, les vars sont inutiles, comme les fermetures & ";", le code lui-même est aussi plus court ... lisez peut-être ceci Comment "minifier" le code Javascript }, vous ne pouvez pas compresser le code suivant dans un code javascript comme celui ci-dessus.)

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

Vous pouvez le faire facilement avec carte et trier:

let unshuffled = ['hello', 'a', 't', 'q', 1, 2, 3, {cats: true}]

let shuffled = unshuffled
  .map((a) => ({sort: Math.random(), value: a}))
  .sort((a, b) => a.sort - b.sort)
  .map((a) => a.value)
  1. Nous plaçons chaque élément du tableau dans un objet et lui donnons une clé de tri aléatoire
  2. Nous trions en utilisant la clé aléatoire
  3. On démappe pour obtenir les objets originaux

Vous pouvez mélanger des tableaux polymorphes et le type est aussi aléatoire que Math.random, ce qui est suffisant pour la plupart des applications.

Étant donné que les éléments sont triés en fonction de clés cohérentes qui ne sont pas régénérées à chaque itération et que chaque comparaison est extraite de la même distribution, tout caractère non aléatoire de la distribution de Math.random est annulé.

44
superluminary

Voici un moyen très simple pour les petits tableaux:

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

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

Ce n'est probablement pas très efficace, mais cela fonctionne très bien pour les petits tableaux. Voici un exemple pour que vous puissiez voir si c'est aléatoire (ou non) et si cela convient à votre cas d'utilisation ou non.

const resultsEl = document.querySelector('#results');
const buttonEl = document.querySelector('#trigger');

const generateArrayAndRandomize = () => {
  const someArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  someArray.sort(() => Math.random() - 0.5);
  return someArray;
};

const renderResultsToDom = (results, el) => {
  el.innerHTML = results.join(' ');
};

buttonEl.addEventListener('click', () => renderResultsToDom(generateArrayAndRandomize(), resultsEl));
<h1>Randomize!</h1>
<button id="trigger">Generate</button>
<p id="results">0 1 2 3 4 5 6 7 8 9</p>

29
Kris Selbekk

Ajouter à la réponse de @Laurens Holsts. C'est compressé à 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
};
21
KingKongFrog

Avec ES2015, vous pouvez utiliser celui-ci:

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

Usage:

[1, 2, 3, 4, 5, 6, 7].shuffle();
14
BrunoLM

Certaines réponses pourraient être abrégées à l'aide de la syntaxe ES6.

ES6 Pure, Itératif

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

Personnellement, j'utilise cette fonction car elle est pure, relativement simple et, d'après mes tests sur Google Chrome, la plus efficace (par rapport à d'autres versions pures). 

Shuffle Array En place

function getShuffledArr (array){
    for (let i = array.length - 1; i > 0; i--) {
        const Rand = Math.floor(Math.random() * (i + 1));
        [array[i], array[Rand]] = [array[Rand], array[i]]
    }
}

Fiabilité et performance

Comme vous pouvez le voir sur cette page, des solutions incorrectes ont été proposées ici par le passé. Ainsi, dans un souci de fiabilité et de performance, j’ai écrit la fonction suivante pour tester toutes les fonctions de randomisation de tableaux pures (sans effets secondaires). Je l'ai utilisé pour tester toutes les options présentées dans cette réponse. 

function testShuffledArrayFun(getShuffledArrayFun){
    const arr = [0,1,2,3,4,5,6,7,8,9]

    let 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 (let i=0 ; i<n ; i++){
        //   We'll call getShuffledArrayFun n times. 
        //   And for each iteration, we'll increment the counter. 
        const 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}`)
}

TypeScript - type pour une fonction de randomisation de tableau pure

Vous pouvez utiliser l'un des éléments suivants. 

type GetShuffledArr= <T>(arr:Array<T>) => Array<T> 
interface IGetShuffledArr{
    <T>(arr:Array<T>): Array<T>
}

Autres options

ES6 Pure, récursive  

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

Cette version est moins efficace que la version pure itérative. 

ES6 Pure using 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]
    })
}

Cette version est légèrement moins efficace que la version pure itérative. 

ES6 Pure using 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]
    )
}

Cette version est légèrement moins efficace que la version pure itérative. 

13
Ben Carp
var shuffle = function(array) {
   temp = [];
   for (var i = 0; i < array.length ; i++) {
     temp.Push(array.splice(Math.floor(Math.random()*array.length),1));
   }
   return temp;
};
13
Tophe

J'ai trouvé cette variante dans les réponses "supprimé par l'auteur" sur un duplicata de cette question. Contrairement à certaines des autres réponses qui ont déjà reçu beaucoup de votes positifs, voici ce qui suit:

  1. Réellement aléatoire
  2. Pas sur place (d'où le nom shuffled plutôt que shuffle)
  3. Pas déjà présent ici avec plusieurs variantes

Voici un jsfiddle montrant qu'il est utilisé .

Array.prototype.shuffled = function() {
  return this.map(function(n){ return [Math.random(), n] })
             .sort().map(function(n){ return n[1] });
}
12
Daniel Martin

Une solution récursive:

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));
};
8
Julian

Fisher-Yates shuffle en javascript. Je poste ceci ici parce que l'utilisation de deux fonctions utilitaires (swap et randInt) clarifie l'algorithme par rapport aux autres réponses ici.

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
dpatru

Vous pouvez le faire facilement avec:

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

Veuillez faire référence à JavaScript Sorting Arrays

7
TinhNQ

Tout d’abord, regardez ici pour une comparaison visuelle des différentes méthodes de tri en javascript.

Deuxièmement, si vous jetez un coup d'œil au lien ci-dessus, vous constaterez que le type random order semble fonctionner relativement bien comparé aux autres méthodes, tout en étant extrêmement facile et rapide à mettre en œuvre, comme indiqué ci-dessous:

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

Edit: comme l'a souligné @gregers, la fonction de comparaison est appelée avec des valeurs plutôt que des indices, c'est pourquoi vous devez utiliser indexOf. Notez que cette modification rend le code moins approprié pour les tableaux de grande taille, car indexOf est exécuté dans le temps O(n).

7
0sh

encore une autre implémentation de Fisher-Yates, en mode strict:

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;
}
5
Raphael C

Toutes les autres réponses sont basées sur Math.random (), qui est rapide mais ne convient pas à la randomisation au niveau cryptographique.

Le code ci-dessous utilise l'algorithme bien connu Fisher-Yates tout en utilisant Web Cryptography API pour niveau de randomisation cryptographique .

var d = [1,2,3,4,5,6,7,8,9,10];

function shuffle(a) {
	var x, t, r = new Uint32Array(1);
	for (var i = 0, c = a.length - 1, m = a.length; i < c; i++, m--) {
		crypto.getRandomValues(r);
		x = Math.floor(r / 65536 / 65536 * m) + i;
		t = a [i], a [i] = a [x], a [x] = t;
	}

	return a;
}

console.log(shuffle(d));

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

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

https://javascript.info/task/shuffle

4
hakiko

Juste pour avoir un doigt dans la tarte. Je présente ici une implémentation récursive de shuffle de Fisher Yates (je pense). Cela donne un caractère aléatoire uniforme.

Remarque: Le ~~ (opérateur double tilde) se comporte en fait comme Math.floor() pour les nombres réels positifs. Juste un raccourci c'est.

var shuffle = a => a.length ? a.splice(~~(Math.random()*a.length),1).concat(shuffle(a))
                            : a;

console.log(JSON.stringify(shuffle([0,1,2,3,4,5,6,7,8,9])));

4
Redu

Une simple modification de answer de CoolAJ86 qui ne modifie pas le tableau d'origine:

 /**
 * Returns a new array whose contents are a shuffled copy of the original array.
 * @param {Array} The items to shuffle.
 * https://stackoverflow.com/a/2450976/1673761
 * https://stackoverflow.com/a/44071316/1673761
 */
const shuffle = (array) => {
  let currentIndex = array.length;
  let temporaryValue;
  let randomIndex;
  const newArray = array.slice();
  // While there remains elements to shuffle...
  while (currentIndex) {
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;
    // Swap it with the current element.
    temporaryValue = newArray[currentIndex];
    newArray[currentIndex] = newArray[randomIndex];
    newArray[randomIndex] = temporaryValue;
  }
  return newArray;
};
4
abumalick

Un certain nombre d'implémentations sont déjà conseillées, mais je pense que nous pouvons simplifier l'utilisation de la boucle forEach. Nous n'avons donc pas à nous soucier de calculer la longueur d'un tableau et nous pouvons également éviter en toute sécurité d'utiliser une variable temporaire.

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

myArr.forEach((val, key) => {
  randomIndex = Math.ceil(Math.random()*(key + 1));
  myArr[key] = myArr[randomIndex];
  myArr[randomIndex] = val;
});
// see the values
console.log('Shuffled Array: ', myArr)
4
Hafizur Rahman

Assez drôle, il n'y avait pas de réponse récursive non mutante:

var shuffle = arr => {
  const recur = (arr,currentIndex)=>{
    console.log("fuck?",JSON.stringify(arr))
    if(currentIndex===0){
      return arr;
    }
    const randomIndex = Math.floor(Math.random() * currentIndex);
    const swap = arr[currentIndex];
    arr[currentIndex] = arr[randomIndex];
    arr[randomIndex] = swap;
    return recur(
      arr,
      currentIndex - 1
    );
  }
  return recur(arr.map(x=>x),arr.length-1);
};

var arr = [1,2,3,4,5,[6]];
console.log(shuffle(arr));
console.log(arr);

3
HMR

la plus courte fonction arrayShuffle

function arrayShuffle(o) {
    for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
    return o;
}
3
Tusko Trush

D'un point de vue théorique, la manière la plus élégante de le faire, à mon humble avis, est d'obtenir un nombre unique aléatoire compris entre 0 et n! -1 et de calculer un mappage un à un de {0, 1, …, n!-1} à toutes les permutations de (0, 1, 2, …, n-1). Tant que vous pouvez utiliser un générateur (pseudo) aléatoire suffisamment fiable pour obtenir un tel nombre sans biais significatif, vous avez suffisamment d'informations pour obtenir ce que vous voulez sans avoir besoin de plusieurs autres nombres aléatoires.

Lorsque vous calculez avec des nombres flottants double précision IEEE754, vous pouvez vous attendre à ce que votre générateur aléatoire fournisse environ 15 décimales. Puisque vous avez 15! = 1 307 674 368 000 (avec 13 chiffres), vous pouvez utiliser les fonctions suivantes avec des tableaux contenant jusqu’à 15 éléments et supposer qu’il n’y aura pas de biais significatif avec les tableaux contenant jusqu’à 14 éléments. Si vous travaillez sur un problème de taille fixe nécessitant de calculer plusieurs fois cette opération aléatoire, vous pouvez essayer le code suivant qui peut est plus rapide que d’autres codes car il utilise Math.random une seule fois (il implique cependant plusieurs opérations de copie. ).

La fonction suivante ne sera pas utilisée, mais je la donne quand même; il renvoie l'indice d'une permutation donnée de (0, 1, 2, …, n-1) en fonction de la correspondance un à un utilisée dans ce message (la plus naturelle lors de l'énumération des permutations); il est prévu de travailler avec 16 éléments maximum:

function permIndex(p) {
    var fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000];
    var tail = [];
    var i;
    if (p.length == 0) return 0;
    for(i=1;i<(p.length);i++) {
        if (p[i] > p[0]) tail.Push(p[i]-1);
        else tail.Push(p[i]);
    }
    return p[0] * fact[p.length-1] + permIndex(tail);
}

La réciproque de la fonction précédente (requise pour votre propre question) est ci-dessous; il est prévu de travailler avec 16 éléments maximum; il retourne la permutation d'ordre n de (0, 1, 2, …, s-1):

function permNth(n, s) {
    var fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000];
    var i, j;
    var p = [];
    var q = [];
    for(i=0;i<s;i++) p.Push(i);
    for(i=s-1; i>=0; i--) {
        j = Math.floor(n / fact[i]);
        n -= j*fact[i];
        q.Push(p[j]);
        for(;j<i;j++) p[j]=p[j+1];
    }
    return q;
}

Maintenant, ce que vous voulez simplement, c'est:

function shuffle(p) {
    var fact = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000];
    return permNth(Math.floor(Math.random()*fact[p.length]), p.length).map(
            function(i) { return p[i]; });
}

Cela devrait fonctionner pour 16 éléments avec un peu de biais théorique (bien que cela ne se remarque pas d'un point de vue pratique); il peut être considéré comme pleinement utilisable pour 15 éléments; avec des tableaux contenant moins de 14 éléments, vous pouvez sans risque considérer qu’il n’y aura absolument aucun parti pris.

3
Thomas Baruchel

Solution en ligne courte moderne utilisant les fonctionnalités de l'ES6:

['a','b','c','d'].map(x => [Math.random(), x]).sort(([a], [b]) => a - b).map(([_, x]) => x);

(à des fins éducatives)

3
icl7126

En utilisant shuffle-array module, vous pouvez mélanger votre tableau. Voici un code simple de celui-ci. 

var shuffle = require('shuffle-array'),
 //collection = [1,2,3,4,5];
collection = ["a","b","c","d","e"];
shuffle(collection);

console.log(collection);

J'espère que cela t'aides.

2
Syed Ayesha Bebe

Si vous envisagez de l’appliquer à in loco ou à un nouveau tableau immuable, en suivant d’autres solutions, voici une implémentation suggérée:

Array.prototype.shuffle = function(local){
  var a = this;
  var newArray = typeof local === "boolean" && local ? this : [];
  for (var i = 0, newIdx, curr, next; i < a.length; i++){
    newIdx = Math.floor(Math.random()*i);
    curr = a[i];
    next = a[newIdx];
    newArray[i] = next;
    newArray[newIdx] = curr;
  }
  return newArray;
};
2
Andre Pastore
Array.prototype.shuffle=function(){
   var len = this.length,temp,i
   while(len){
    i=Math.random()*len-- |0;
    temp=this[len],this[len]=this[i],this[i]=temp;
   }
   return this;
}
2
user1289673

Aléatoire tableau en utilisant array.splice () 

function shuffleArray(array) {
   var temp = [];
   var len=array.length;
   while(len){
      temp.Push(array.splice(Math.floor(Math.random()*array.length),1)[0]);
      len--;
   }
   return temp;
}
//console.log("Here >>> "+shuffleArray([4,2,3,5,8,1,0]));

démo

2

Au hasard, soit Push ou unshift (ajouter au début).

['a', 'b', 'c', 'd'].reduce((acc, el) => {
  Math.random() > 0.5 ? acc.Push(el) : acc.unshift(el);
  return acc;
}, []);
2
Pawel

Je vois que personne n’a encore donné de solution qui puisse être concaténée sans prolonger le prototype Array (ce qui est une mauvaise pratique ). En utilisant reduce() légèrement moins connu, nous pouvons facilement mélanger de manière à permettre la concaténation:

var randomsquares = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle).map(n => n*n);

Vous voudrez probablement passer le second paramètre [], sinon, si vous essayez de faire cela sur un tableau vide, cela échouera:

// Both work. The second one wouldn't have worked as the one above
var randomsquares = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle, []).map(n => n*n);
var randomsquares = [].reduce(shuffle, []).map(n => n*n);

Définissons shuffle comme:

var shuffle = (Rand, one, i, orig) => {
  if (i !== 1) return Rand;  // Randomize it only once (arr.length > 1)

  // You could use here other random algorithm if you wanted
  for (let i = orig.length; i; i--) {
    let j = Math.floor(Math.random() * i);
    [orig[i - 1], orig[j]] = [orig[j], orig[i - 1]];
  }

  return orig;
}

Vous pouvez le voir en action dans JSFiddle ou ici:

var shuffle = (all, one, i, orig) => {
    if (i !== 1) return all;

    // You could use here other random algorithm here
    for (let i = orig.length; i; i--) {
        let j = Math.floor(Math.random() * i);
        [orig[i - 1], orig[j]] = [orig[j], orig[i - 1]];
    }

    return orig;
}

for (var i = 0; i < 5; i++) {
  var randomarray = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle, []);
  console.log(JSON.stringify(randomarray));
}

2

Ronald Fisher et Frank Yates mélangent

Version ES2015 (ES6)

Array.prototype.shuffle2 = function () {
    this.forEach(
        function (v, i, a) {
            let j = Math.floor(Math.random() * (i + 1));
            [a[i], a[j]] = [a[j], a[i]];
        }
    );
    return this;
}

Version ES2015 (ES6) optimisée pour Jet

Array.prototype.shuffle3 = function () {
    var m = this.length;
    while (m) {
        let i = Math.floor(Math.random() * m--);
        [this[m], this[i]] = [this[i], this[m]];
    }
    return this;
}
2
SynCap

Tableau aléatoire

 var arr = ['Apple','cat','Adam','123','Zorro','petunia']; 
 var n = arr.length; var tempArr = [];

 for ( var i = 0; i < n-1; i++ ) {

    // The following line removes one random element from arr 
     // and pushes it onto tempArr 
     tempArr.Push(arr.splice(Math.floor(Math.random()*arr.length),1)[0]);
 }

 // Push the remaining item onto tempArr 
 tempArr.Push(arr[0]); 
 arr=tempArr; 
2
vickisys

Je pensais à oneliner pour coller dans la console. Tous les trucs avec .sort donnaient de faux résultats, voici mon implémentation:

 ['Bob', 'Amy', 'Joy'].map((person) => `${Math.random().toFixed(10)}${person}`).sort().map((person) => person.substr(12));

Mais ne l'utilisez pas dans le code de production, ce n'est pas optimal et ne fonctionne qu'avec des chaînes.

2
Cezary Daniel Nowak

function shuffleArray(array) {
        // Create a new array with the length of the given array in the parameters
        const newArray = array.map(() => null);

        // Create a new array where each index contain the index value
        const arrayReference = array.map((item, index) => index);

        // Iterate on the array given in the parameters
        array.forEach(randomize);
        
        return newArray;

        function randomize(item) {
            const randomIndex = getRandomIndex();

            // Replace the value in the new array
            newArray[arrayReference[randomIndex]] = item;
            
            // Remove in the array reference the index used
            arrayReference.splice(randomIndex,1);
        }

        // Return a number between 0 and current array reference length
        function getRandomIndex() {
            const min = 0;
            const max = arrayReference.length;
            return Math.floor(Math.random() * (max - min)) + min;
        }
    }
    
console.log(shuffleArray([10,20,30,40,50,60,70,80,90,100]));

2
Julian FARHI
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
    }
};

Il suffit de passer le tableau pour fonctionner et obtenir en retour le tableau mélangé

2
Mayur Nandane
// 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];
    })
}
2
Mudlabs

Pour ceux d'entre nous qui ne sont pas très doués mais qui ont accès aux merveilles de lodash, il existe un procédé tel que lodash.shuffle

1
iPhoney

Nous sommes toujours en train de brouiller des tableaux en 2019, donc voici mon approche, qui me semble nette et rapide :

const src = [...'abcdefg'];

const shuffle = arr => arr.reduceRight((res,_,__,arr) => [...res,arr.splice(~~(Math.random()*arr.length),1)[0]],[]);

console.log(shuffle(src));
.as-console-wrapper {
  max-height: 100% !important;
  top: 0;
}
1
Yevgen Gorbunkov

Reconstruire tout le tableau, un par un, en plaçant chaque élément à un endroit aléatoire.

[1,2,3].reduce((a,x,i)=>{a.splice(Math.floor(Math.random()*(i+1)),0,x);return a},[])
var ia= [1,2,3];
var it= 1000;
var f = (a,x,i)=>{a.splice(Math.floor(Math.random()*(i+1)),0,x);return a};
var a = new Array(it).fill(ia).map(x=>x.reduce(f,[]));
var r = new Array(ia.length).fill(0).map((x,i)=>a.reduce((i2,x2)=>x2[i]+i2,0)/it)

console.log("These values should be quite equal:",r);
1
Alex Szücs

Cette variante de Fisher-Yates est légèrement plus efficace car elle évite de permuter un élément avec lui-même:

function shuffle(array) {
  var elementsRemaining = array.length, temp, randomIndex;
  while (elementsRemaining > 1) {
    randomIndex = Math.floor(Math.random() * elementsRemaining--);
    if (randomIndex != elementsRemaining) {
      temp = array[elementsRemaining];
      array[elementsRemaining] = array[randomIndex];
      array[randomIndex] = temp;
    }
  }
  return array;
}
1
Noel Hartsell

J'ai écrit une fonction de lecture aléatoire par moi-même. La différence ici est qu'il ne répétera jamais une valeur (vérifie le code pour cela): -

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; }
1
Saksham Khurana
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0].sort((x, z) => {
    ren = Math.random();
    if (ren == 0.5) return 0;
    return ren > 0.5 ? 1 : -1
})
0
Rafi Henig

Une solution fonctionnelle utilisant 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])
0
thomas-peter

$=(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());

0
Abdennour TOUMI

Mélanger tableau de chaînes:

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;
 }
0
Mubeen Khan