it-swarm.com.de

Wie man ein JavaScript-Array randomisiert (mischt)?

Ich habe ein Array wie dieses:

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

Wie kann ich es randomisieren/mischen?

979
Click Upvote

Der De-facto-Shuffle-Algorithmus ist der Fisher-Yates (alias Knuth) Shuffle.

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

Sie können eine großartige Visualisierung hier (und den ursprünglichen Beitrag damit verbunden ) sehen.

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

Einige weitere Informationen über den Algorithmus verwendet.

1222
ChristopheD

Hier ist eine JavaScript-Implementierung des Durstenfeld shuffle , einer computeroptimierten Version von 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;
    }
}

Der Fisher-Yates-Algorithmus wählt ein zufälliges Element für jedes ursprüngliche Array-Element aus und schließt es dann von der nächsten Ziehung aus. Genauso wie das zufällige Auslesen eines Kartensets.

Dieser Ausschluss erfolgt auf clevere Weise (von Durstenfeld für die Verwendung durch Computer erfunden), indem das ausgewählte Element durch das aktuelle Element ausgetauscht wird und dann das nächste zufällige Element aus dem Rest ausgewählt wird. Für eine optimale Effizienz läuft die Schleife rückwärts, sodass die Zufallsauswahl vereinfacht wird (sie kann immer bei 0 beginnen), und das letzte Element wird übersprungen, da keine anderen Optionen mehr vorhanden sind.

Die Laufzeit dieses Algorithmus ist O (n). Beachten Sie, dass der Shuffle direkt durchgeführt wird. Wenn Sie also das ursprüngliche Array nicht ändern möchten, erstellen Sie zuerst eine Kopie davon mit .slice(0).

Aktualisierung auf ES6/ECMAScript 2015

Mit dem neuen ES6 können wir zwei Variablen gleichzeitig zuweisen. Dies ist besonders praktisch, wenn wir die Werte von zwei Variablen austauschen möchten, da dies in einer Codezeile möglich ist. Hier ist eine kürzere Form der gleichen Funktion, die diese Funktion verwendet. 

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

[Community edit: Diese Antwort ist falsch; Zeige Kommentare. Sie wird hier zum Nachschlagen gelassen, weil die Idee nicht so selten ist.]

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

Man könnte (oder sollte) es als Prototyp von Array verwenden:

Von 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

Verwenden Sie die Bibliothek untererscore.js. Die Methode _.shuffle() ist für diesen Fall nett. Hier ein Beispiel mit der Methode:

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

NEU!

Kürzerer & wahrscheinlich * schnellerer Fisher-Yates-Shuffle-Algorithmus

  1. es verwendet, während ---
  2. bitweise nach Etage (Zahlen bis zu 10 Dezimalstellen (32 Bit))
  3. unnötige Verschlüsse und andere Sachen entfernt

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
}

skriptgröße (mit fy als Funktionsname): 90 Byte 

DEMOhttp://jsfiddle.net/vvpoma8w/

* wahrscheinlich schneller in allen Browsern außer Chrome.

Wenn Sie Fragen haben, fragen Sie einfach.

EDIT

ja es geht schneller

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

mit den am besten gewählten Funktionen.

EDIT Es gab eine zu hohe Berechnung (brauchen Sie nicht --c + 1) und niemand hat

kürzer (4 Byte) und schneller (testen Sie es!).

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
}

Das Cachen an einem anderen Ort var rnd=Math.random und die Verwendung von rnd() würde die Leistung bei großen Arrays ebenfalls leicht erhöhen.

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

Readable version (Verwenden Sie die Originalversion. Dies ist langsamer, vars sind unbrauchbar, wie die Verschlüsse & ";", der Code selbst ist auch kürzer ... lesen Sie vielleicht dieses How to 'minify' Javascript-Code , übrigens können Sie den folgenden Code nicht in einem JavaScript-Minifier wie dem obigen komprimieren.)

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

Das geht ganz einfach mit Karte und Sortierung:

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. Wir fügen jedes Element im Array in ein Objekt ein und geben ihm einen zufälligen Sortierschlüssel
  2. Wir sortieren mit dem Zufallsschlüssel
  3. Wir lösen die Zuordnung auf, um die ursprünglichen Objekte zu erhalten

Sie können polymorphe Arrays mischen, und die Sortierung ist so zufällig wie bei Math.random, was für die meisten Zwecke gut genug ist.

Da die Elemente nach konsistenten Schlüsseln sortiert werden, die nicht bei jeder Iteration neu generiert werden und jeder Vergleich aus derselben Verteilung zieht, wird jede Nicht-Zufälligkeit in der Verteilung von Math.random aufgehoben.

44
superluminary

Ein sehr einfacher Weg für kleine Arrays ist einfach:

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

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

Es ist wahrscheinlich nicht sehr effizient, aber für kleine Arrays funktioniert das gut. Hier ist ein Beispiel, damit Sie sehen können, wie zufällig (oder nicht) es ist und ob es zu Ihrer Anwendung passt oder nicht.

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

Hinzufügen zur Antwort von @Laurens Holsts. Dies ist zu 50% komprimiert.

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

Mit ES2015 können Sie diese verwenden:

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

Verwendungszweck:

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

Einige Antworten konnten mit der ES6-Syntax abgekürzt werden.

ES6 Pure, iterativ

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

Ich persönlich nutze diese Funktion, da sie rein und relativ einfach ist und laut meinen Tests bei Google Chrome am effizientesten ist (im Vergleich zu anderen reinen Versionen). 

Shuffle Array An Ort und Stelle

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

Zuverlässigkeit und Leistung

Wie Sie auf dieser Seite sehen können, wurden hier in der Vergangenheit falsche Lösungen angeboten. Mit Blick auf Zuverlässigkeit und Leistung schrieb ich die folgende Funktion, um alle reinen Array-Randomisierungsfunktionen (ohne Nebenwirkungen) zu testen. Ich habe es verwendet, um alle in dieser Antwort dargestellten Optionen zu testen. 

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 - Typ für eine reine Array-Zufallsfunktion

Sie können eines der folgenden verwenden. 

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

Andere Optionen

ES6 rein, rekursiv  

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

Diese Version ist weniger effizient als die iterative reine Version. 

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

Diese Version ist etwas weniger effizient als die iterative reine Version. 

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

Diese Version ist etwas weniger effizient als die iterative reine Version. 

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

Ich fand diese Variante in den Antworten "Von Autor gelöscht" auf einem Duplikat dieser Frage hängen. Im Gegensatz zu einigen anderen Antworten, die bereits viele Upvotes enthalten, ist dies Folgendes:

  1. Eigentlich zufällig
  2. Nicht vorhanden (daher shuffled Name statt shuffle)
  3. Hier bei mehreren Varianten noch nicht vorhanden

Hier ist eine jsfiddle, die es im Einsatz zeigt .

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

Eine rekursive Lösung:

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 mischen in Javascript. Ich poste dies hier, weil die Verwendung von zwei Hilfsfunktionen (Swap und RandInt) den Algorithmus im Vergleich zu den anderen Antworten verdeutlicht.

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

Sie können es leicht mit:

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

Bitte beziehen Sie sich auf JavaScript Sorting Arrays

7
TinhNQ

Werfen Sie einen Blick auf hier für einen großartigen visuellen Vergleich verschiedener Sortiermethoden in Javascript.

Zweitens: Wenn Sie sich den Link oben kurz ansehen, werden Sie feststellen, dass die Sortierung von random order im Vergleich zu den anderen Methoden relativ gut zu sein scheint, während sie wie unten gezeigt extrem einfach und schnell zu implementieren ist:

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

Edit: Wie von @gregers angegeben, wird die Compare-Funktion mit Werten statt mit Indizes aufgerufen. Daher müssen Sie indexOf verwenden. Beachten Sie, dass diese Änderung den Code für größere Arrays weniger geeignet macht, da indexOf in der Zeit O(n) ausgeführt wird.

7
0sh

eine Shuffle-Funktion, die das Quell-Array nicht ändert

Update: Hier schlage ich einen relativ einfachen einfachen (nicht aus Komplexität - Perspektive) und kurzen Algorithmus vor, der mit kleinen Arrays gut funktioniert, aber Es wird definitiv viel mehr kosten als der klassische Durstenfeld Algorithmus, wenn Sie mit großen Arrays arbeiten. Sie finden das Durstenfeld in einer der Top-Antworten auf diese Frage.

Ursprüngliche Antwort:

Wenn Sie nicht wünschen Ihre Shuffle-Funktion verwenden, um das source array zu mutieren, können Sie es in eine lokale Variable kopieren und den Rest mit einer einfachen Mischlogik erledigen.

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

Mischlogik: Heben Sie einen zufälligen Index auf, fügen Sie das entsprechende Element zum Ergebnisarray hinzu und löschen Sie es aus der Quellarray-Kopie. Wiederholen Sie diese Aktion, bis das Quellarray leer erhält.

Und wenn Sie es wirklich kurz halten wollen, hier ist, wie weit ich kommen könnte:

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

eine weitere Implementierung von Fisher-Yates im strikten Modus:

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

Alle anderen Antworten basieren auf Math.random (), das zwar schnell, aber nicht für die Randomisierung auf kryptografischer Ebene geeignet ist.

Der folgende Code verwendet den bekannten Fisher-Yates-Algorithmus, während Web Cryptography API für die kryptographische Ebene der Randomisierung verwendet wird.

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

Nur um einen Finger in der Torte zu haben. Hier präsentiere ich eine rekursive Implementierung von Fisher Yates shuffle (denke ich). Es gibt einheitliche Zufälligkeit.

Hinweis: Der ~~ (Doppel-Tilde-Operator) verhält sich für positive reelle Zahlen tatsächlich wie Math.floor(). Nur eine Abkürzung ist es.

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

Eine einfache Modifikation von CoolAJ86 answer , die das ursprüngliche Array nicht ändert:

 /**
 * 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

Zwar gibt es bereits eine Reihe von Implementierungen, aber ich denke, wir können die forEach-Schleife kürzer und einfacher machen, so dass wir uns keine Sorgen um die Berechnung der Arraylänge machen müssen und auch die Verwendung einer temporären Variablen vermeiden.

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

Lustigerweise gab es keine nicht mutierende rekursive Antwort:

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

die kürzeste arrayShuffle-Funktion

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

Aus theoretischer Sicht ist es meiner bescheidenen Meinung nach am elegantesten, eine einzelne Zufallszahl zwischen und n! -1 und um eine Eins-zu-Eins-Zuordnung von {0, 1, …, n!-1} Zu allen Permutationen von (0, 1, 2, …, n-1) Zu berechnen. Solange Sie einen (Pseudo-) Zufallsgenerator verwenden können, der zuverlässig genug ist, um eine solche Zahl ohne signifikante Verzerrung zu erhalten, verfügen Sie über genügend Informationen, um das zu erreichen, was Sie wollen, ohne mehrere andere Zufallszahlen zu benötigen.

Wenn Sie mit IEEE754-Gleitkommazahlen doppelter Genauigkeit rechnen, können Sie davon ausgehen, dass Ihr Zufallsgenerator etwa 15 Dezimalstellen liefert. Da Sie 15! = 1,307,674,368,0 (mit 13 Ziffern) haben, können Sie die folgenden Funktionen mit Arrays mit bis zu 15 Elementen verwenden und davon ausgehen, dass bei Arrays mit bis zu 14 Elementen keine signifikante Verzerrung vorliegt. Wenn Sie an einem Problem mit fester Größe arbeiten, bei dem diese Mischoperation mehrmals ausgeführt werden muss, möchten Sie möglicherweise den folgenden Code ausprobieren, der möglicherweise schneller ist als andere Codes, da nur Math.random Verwendet wird einmalig (es sind jedoch mehrere Kopiervorgänge erforderlich).

Die folgende Funktion wird nicht verwendet, aber ich gebe es trotzdem; es gibt den Index einer gegebenen Permutation von (0, 1, 2, …, n-1) gemäß der Eins-zu-Eins-Zuordnung zurück, die in dieser Nachricht verwendet wird (die natürlichste bei der Aufzählung von Permuationen); Es ist vorgesehen, mit bis zu 16 Elementen zu arbeiten:

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

Der Kehrwert der vorherigen Funktion (erforderlich für Ihre eigene Frage) ist unten angegeben. es ist vorgesehen, mit bis zu 16 Elementen zu arbeiten; es gibt die Permutation der Reihenfolge n von (0, 1, 2, …, s-1) zurück:

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

Nun, was Sie nur wollen, ist:

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

Es sollte für bis zu 16 Elemente mit einer gewissen theoretischen Verzerrung funktionieren (obwohl dies aus praktischer Sicht nicht zu bemerken ist). es kann für 15 Elemente als voll verwendbar angesehen werden; Bei Arrays mit weniger als 14 Elementen können Sie mit Sicherheit davon ausgehen, dass keine Verzerrung vorliegt.

3
Thomas Baruchel

Moderne Inline-Kurzlösung mit ES6-Funktionen:

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

(für Bildungszwecke)

3
icl7126

Mit shuffle-array module können Sie Ihr Array mischen. Hier ist ein einfacher Code davon. 

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

console.log(collection);

Hoffe das hilft.

2

Wenn Sie die Anwendung auf in loco oder auf ein neues unveränderliches Array anwenden, folgen Sie den folgenden Lösungsansätzen. Hier ist ein Vorschlag zur Implementierung:

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

Array mit Array.splice () randomisieren 

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

Demo

2

Nach dem Zufallsprinzip entweder drücken oder loslassen (am Anfang hinzufügen).

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

Ich sehe, niemand hat bisher eine Lösung gegeben, die verkettet werden kann, ohne den Array-Prototyp zu erweitern (was eine schlechte Praxis ist). Mit dem etwas weniger bekannten reduce() können wir das Shuffling leicht auf eine Weise durchführen, die eine Verkettung ermöglicht:

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

Sie möchten wahrscheinlich den zweiten Parameter [] übergeben, da andernfalls ein Fehler auftreten würde, wenn Sie versuchen, dies an einem leeren Array zu tun:

// 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);

Wir definieren shuffle als:

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

Sie können es in Aktion in JSFiddle oder hier sehen:

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 und Frank Yates mischen sich

Veröffentlichung von 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;
}

Jet-optimierte Version von ES2015 (ES6)

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

Array randomisieren

 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

Ich dachte darüber nach, welchen Oneliner in die Konsole einzufügen. Alle Tricks mit .sort lieferten falsche Ergebnisse, hier ist meine Implementierung:

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

Verwenden Sie es jedoch nicht im Produktionscode, es ist nicht optimal und funktioniert nur mit Strings.

2

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

Übergeben Sie einfach das Array, um zu funktionieren und erhalten Sie das gemischte Array

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

Für diejenigen von uns, die nicht besonders begabt sind, aber Zugang zu den Wundern von lodash haben, gibt es so etwas wie lodash.shuffle

1
iPhoney

Wir mischen immer noch Arrays im Jahr 2019, also hier ist mein Ansatz, der mir ordentlich und schnell vorkommt:

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

d3.js liefert eine eingebaute Version des Fisher-Yates-Shuffle :

console.log(d3.shuffle(["a", "b", "c", "d"]));
<script src="http://d3js.org/d3.v5.min.js"></script>

d3.shuffle (array [ lo [ hi]]) <>

Randomisiert die Reihenfolge des angegebenen Arrays mithilfe von Fisher-Yates-Shuffle .

1
Xavier Guihot

Erstellen Sie das gesamte Array nacheinander neu, indem Sie jedes Element an einer beliebigen Stelle platzieren.

[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

Diese Variante von Fisher-Yates ist etwas effizienter, da sie den Austausch eines Elements mit sich selbst vermeidet:

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

Ich habe selbst eine Shuffle-Funktion geschrieben. Der Unterschied hier ist, dass es niemals einen Wert wiederholt (prüft den Code dafür):

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

Eine funktionale Lösung mit 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

Zufällige Anordnung von Zeichenfolgen:

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