Jak losować (shuffle) tablicę JavaScript?
Mam taką tablicę:
var arr1 = ["a", "b", "c", "d"];
Jak mogę losować / tasować?
30 answers
De facto bezstronny algorytm shuffle jest Fisher-Yates (aka Knuth) Shuffle.
Zobacz https://github.com/coolaj86/knuth-shuffle
Możesz zobaczyć wielką wizualizację tutaj (i oryginalny post połączony z tym)
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);
Trochę więcej informacji o zastosowanym algorytmie .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-11 04:18:38
Jest to implementacja JavaScript durstenfeld shuffle, zoptymalizowanej komputerowo wersji 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;
}
}
Algorytm Fisher-Yates działa poprzez wybranie jednego losowego elementu dla każdego oryginalnego elementu tablicy, a następnie wykluczenie go z następnego losowania. Zupełnie jak losowe wybieranie z talii kart.
To wykluczenie odbywa się w sprytny sposób (wymyślony przez Durstenfelda do użytku przez komputery) poprzez zamianę wybranego elementu na bieżący element, a następnie wybierając kolejny losowy element z reszty. Dla optymalnej wydajności pętla biegnie do tyłu, dzięki czemu losowy pick jest uproszczony (zawsze może zaczynać się od 0) i pomija ostatni element, ponieważ nie ma już innych opcji.
Czas działania tego algorytmu wynosi O (n). Należy pamiętać, że tasowanie odbywa się na miejscu. Jeśli więc nie chcesz modyfikować oryginalnej tablicy, najpierw zrób jej kopię za pomocą .slice(0)
.
Aktualizacja do ES6 / ECMAScript 2015
Nowy ES6 pozwala nam przypisać dwie zmienne jednocześnie. Jest to szczególnie przydatne, gdy chcemy zamienić wartości dwóch zmiennych, ponieważ możemy to zrobić w jednej linii kodu. Oto krótsza forma tej samej funkcji, wykorzystująca tę funkcję.
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]]; // eslint-disable-line no-param-reassign
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-15 14:40:36
[edycja społeczności: ta odpowiedź jest nieprawidłowa; Zobacz komentarze. Zostawia się go tutaj do przyszłego odniesienia, ponieważ pomysł nie jest tak rzadki.]
[1,2,3,4,5,6].sort(function() {
return .5 - Math.random();
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-22 22:19:57
Można (lub powinno) używać go jako prototype z tablicy:
From:
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-16 02:53:06
Użyj podkreślenia.biblioteka js. Metoda _.shuffle()
jest dobra w tym przypadku.
Oto przykład metody:
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();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-12 03:05:51
Nowość!
Shorter & probably *faster Fisher-Yates shuffle algorithm
- używa while - - -
- bitowo do podłogi (liczby do 10 cyfr dziesiętnych (32bit))
- usunięte niepotrzebne zamknięcia i inne rzeczy
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
}
Rozmiar skryptu (z fy jako nazwą funkcji): 90bytes
DEMO http://jsfiddle.net/vvpoma8w/
*szybciej chyba we wszystkich przeglądarkach oprócz chrome.
Jeśli masz jakieś pytania po prostu pytaj.
EDIT
Yes it is faster
Osiągi: http://jsperf.com/fyshuffle
Korzystanie z topowych funkcji.
EDIT Nie było obliczenia w nadmiarze (nie trzeba --c+1) i nikt nie zauważył
Shorter (4bytes)&faster (test it!).
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
}
Buforowanie gdzie indziej var rnd=Math.random
a następnie użycie rnd()
również zwiększyłoby nieco wydajność na dużych tablice.
Http://jsfiddle.net/vvpoma8w/2/
Wersja czytelna (użyj wersji oryginalnej. jest to wolniejsze, vary są bezużyteczne, podobnie jak zamknięcia&";", sam kod jest również krótszy ... może przeczytaj to jak "minify" kod Javascript , btw nie jesteś w stanie skompresować poniższego kodu w minifierze javascript, takim jak powyższy.)
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
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:44
Możesz to zrobić łatwo za pomocą mapy i sortowania:
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)
- umieszczamy każdy element w tablicy w obiekcie i nadajemy mu losowy klucz sortowania
- sortujemy za pomocą Losowego klucza
- unmap, aby uzyskać oryginalne obiekty
Możesz przetasować tablice polimorficzne, a sortowanie jest tak losowe, jak matematyka.przypadkowy, który jest wystarczająco dobry dla większości celów.
Ponieważ elementy są sortowane według spójnych kluczy, które nie są regenerowane w każdej iteracji, a każde porównanie ciągnie z tego samego rozkładu, Dowolna nie przypadkowość w rozkładzie matematyki.losowe jest anulowane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-03 11:39:15
Bardzo prosty sposób dla małych tablic jest po prostu taki:
const someArray = [1, 2, 3, 4, 5];
someArray.sort(() => Math.random() - 0.5);
Prawdopodobnie nie jest to zbyt wydajne, ale w przypadku małych tablic działa to dobrze. Oto przykład, dzięki któremu możesz zobaczyć, jak losowy (lub nie) jest on i czy pasuje do twojej bazy użytkowników, czy nie.
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>
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-17 14:01:14
Dodawanie do @Laurens Holsts odpowiedz. To jest w 50% skompresowane.
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
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-12 03:04:31
Z ES2015 możesz użyć tego:
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;
}
Użycie:
[1, 2, 3, 4, 5, 6, 7].shuffle();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-24 04:26:13
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;
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-12 03:02:36
Znalazłem ten wariant wiszący w odpowiedziach "deleted by author" na duplikacie tego pytania. W przeciwieństwie do innych odpowiedzi, które mają już wiele głosów, jest to:
- właściwie random
- nie na miejscu (stąd nazwa {[1] } a nie
shuffle
) - nie występuje już tutaj z wieloma wariantami
Oto jsfiddle pokazujący go w użyciu .
Array.prototype.shuffled = function() {
return this.map(function(n){ return [Math.random(), n] })
.sort().map(function(n){ return n[1] });
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-10 14:56:58
Rozwiązanie rekurencyjne:
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));
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-26 08:40:01
Z ES6, 2018
Niektóre odpowiedzi można skrócić za pomocą najnowszego ES6.
Shuffle Array In place
function shuffleArray (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]];
}
}
Za pomocą ES6 możemy przypisać dwie wartości jednocześnie. Jest to szczególnie przydatne w linii 4 powyżej, gdzie dwie zmienne są zamieniane w jednym wierszu kodu.
Pozostaw oryginalną tablicę nienaruszoną i zwróć tablicę tasowaną
Jeśli chcesz stworzyć bardziej czystą funkcję i pozostawić oryginalną tablicę nienaruszoną, możesz po prostu powielić tablicę, a następnie uruchomić tę samą algorytm.
function getShuffledArray (arr){
let newArr = [...arr]
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;
}
Algorytm rosnący
Poniższy algorytm wykorzystuje pętlę wstępującą. Jest mniej intuicyjny, ale krótki i ważny.
function getShuffledArrayAsc (arr){
let newArr = [...arr];
for (let i = 1; i < newArr.length ; i++) {
const rand = Math.floor( Math.random() * (i + 1) );
[newArr[i], newArr[rand]] = [newArr[rand], newArr[i]];
}
return newArr;
}
Sprawdzanie niezawodności funkcji Randomizującej
Powyższe funkcje prezentowały równomierny rozkład po przekazaniu do' testShuffledArrayFun ' poniżej, zarówno w Chrome, jak i w Node. Jest to zgodne z tym, czego oczekiwalibyśmy od funkcji randomizującej.
function testShuffledArrayFun(getShuffledArrayFun){
// Tests the reliability of the suffleArrayFunction, by callying it 1,000 times and presenting the distribution.
const testArr = [0,1,2,3,4];
const countArr = testArr.map( position => // for for each possible position in the shuffledArr, for each possible value, we'll create a counter. the counter of value 0 in position 0 will be countArr[0][0]
testArr.map( value => 0)
)
const n = 10000;
for (var i=0 ; i<n ; i++){
// We'll call getShuffledArrayFun for n times. For each shuffledArray we receive we'll increment the counterArr accordingly. At the end we'll print the distribution.
var shuffledArr = getShuffledArrayFun(testArr);
shuffledArr.forEach(
(value, key) => {countArr[key][value]++}
);
}
countArr.forEach(
(valueCountArr,key) => {
console.log(`Position ${key}:`);
valueCountArr.forEach(
(count,originalValue) => {
console.log(`The Value ${originalValue} appeared ${count*100/n}% `);
}
);
}
);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-22 04:09:58
Fisher-Yates shuffle w javascript. Zamieszczam to tutaj, ponieważ użycie dwóch funkcji użytkowych (swap i randInt) wyjaśnia algorytm w porównaniu z innymi odpowiedziami tutaj.
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);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-01 01:53:39
Po pierwsze, spójrz tutaj, aby uzyskać świetne wizualne porównanie różnych metod sortowania w javascript.
Po drugie, jeśli spojrzysz na powyższy link, przekonasz się, że sortowanie random order
wydaje się działać stosunkowo dobrze w porównaniu do innych metod, a jednocześnie jest niezwykle łatwe i szybkie w implementacji, jak pokazano poniżej:
function shuffle(array) {
var random = array.map(Math.random);
array.sort(function(a, b) {
return random[array.indexOf(a)] - random[array.indexOf(b)];
});
}
Edit: jak zauważył @gregers, funkcja compare jest wywoływana z wartościami, a nie indeksami, dlatego potrzebujesz aby użyć indexOf
. Zauważ, że ta zmiana sprawia, że kod jest mniej odpowiedni dla większych tablic, ponieważ indexOf
działa w czasie O (n).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-15 15:00:11
Kolejna implementacja Fishera-Yatesa, używająca trybu ścisłego:
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-21 13:20:28
Możesz to zrobić łatwo z:
// array
var fruits = ["Banana", "Orange", "Apple", "Mango"];
// random
fruits.sort(function(a, b){return 0.5 - Math.random()});
// out
console.log(fruits);
Proszę odnieść się do JavaScript sortowanie tablic
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-20 06:59:22
Funkcja shuffle, która nie zmienia tablicy źródłowej
Update : tutaj sugeruję stosunkowo prosty (nie z perspektywy złożoność) i krótkialgorytm, który sprawdzi się w przypadku małych tablic, ale na pewno będzie kosztować znacznie więcej niż klasyczny algorytm Durstenfelda , Gdy masz do czynienia z dużymi tablicami. Możesz znaleźć Durstenfeld w jednej z najlepszych odpowiedzi na to pytanie.
oryginał ODPOWIEDŹ:
Jeśli nie chcesz, aby twoja funkcja shuffle zmutowała tablicę źródłową, możesz skopiować ją do zmiennej lokalnej, a następnie wykonać resztę za pomocą prostej logiki tasowania.
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;
}
tasowanie logiki: pobranie losowego indeksu, następnie dodanie odpowiedniego elementu do tablicy wyników i usunięcie go z kopii tablicy źródłowej . Powtórz tę czynność, aż tablica źródłowa zostanie pusta .
I jeśli naprawdę tego chcesz krótko, oto jak daleko mogłem się dostać:
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-20 11:08:18
Wszystkie pozostałe odpowiedzi są oparte na matematyce.random (), która jest szybka, ale nie nadaje się do randomizacji na poziomie kryptograficznym.
Poniższy kod wykorzystuje dobrze znany algorytm Fisher-Yates
, wykorzystując Web Cryptography API
dla kryptograficznego poziomu randomizacji .
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));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-23 21:33:39
Żeby mieć palec w cieście. Tutaj przedstawiam rekurencyjną implementację Fisher Yates shuffle (tak myślę). Daje jednolitą przypadkowość.
Uwaga: ~~
(operator podwójnej tyldy) w rzeczywistości zachowuje się jak Math.floor()
dla dodatnich liczb rzeczywistych. To tylko skrót.
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])));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-20 08:08:18
Chociaż jest już wiele implementacji, ale czuję, że możemy to skrócić i ułatwić za pomocą pętli forEach, więc nie musimy się martwić o obliczanie długości tablicy, a także możemy bezpiecznie uniknąć użycia zmiennej tymczasowej.
var arr1 = ["a", "b", "c", "d"];
arr1.forEach((val, key) => {
randomIndex = Math.ceil(Math.random()*(key + 1));
arr1[key] = arr1[randomIndex];
arr1[randomIndex] = val;
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-07 11:25:58
Najkrótsza arrayShuffle
Funkcja
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-17 18:13:49
Z teoretycznego punktu widzenia, najbardziej eleganckim sposobem, moim skromnym zdaniem, jest uzyskanie pojedynczej losowej liczby pomiędzy 0 i n!-1 i obliczyć odwzorowanie jeden do jednego z {0, 1, …, n!-1}
dla wszystkich permutacji (0, 1, 2, …, n-1)
. Tak długo, jak możesz użyć (pseudo)generatora losowego wystarczająco niezawodnego, aby uzyskać taką liczbę bez żadnego znaczącego uprzedzenia, masz w nim wystarczająco dużo informacji, aby osiągnąć to, czego chcesz, bez potrzeby kilku innych losowych liczby.
Podczas obliczania liczb zmiennoprzecinkowych z podwójną precyzją IEEE754, można oczekiwać, że generator losowy dostarczy około 15 miejsc po przecinku. Ponieważ masz 15!=1,307,674,368,000 (z 13 cyframi), można używać następujących funkcji z tablicami zawierającymi do 15 elementów i zakładać, że nie będzie znaczącego błędu przy tablicach zawierających do 14 elementów. Jeśli pracujesz nad problemem o stałym rozmiarze wymagającym wielokrotnego obliczania tej operacji shuffle, możesz spróbować po kodzie, który może być szybszy od innych kodów, ponieważ używa Math.random
tylko raz (wymaga jednak kilku operacji kopiowania).
Następująca funkcja nie zostanie użyta, ale i tak ją podaję; zwraca indeks danej permutacji (0, 1, 2, …, n-1)
zgodnie z mapowaniem jeden do jednego używanym w tej wiadomości (najbardziej naturalnym przy wyliczaniu permutacji); jest przeznaczona do pracy z maksymalnie 16 elementami:
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);
}
Odwrotność poprzedniej funkcji (wymagana dla Twoje własne pytanie) znajduje się poniżej; jest przeznaczony do pracy z maksymalnie 16 elementami; zwraca permutację rzędu n z (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;
}
Teraz, co chcesz tylko jest:
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]; });
}
Powinien działać dla maksymalnie 16 elementów z niewielkim teoretycznym odchyleniem (choć niezauważalnym z praktycznego punktu widzenia); może być postrzegany jako w pełni użyteczny dla 15 elementów; z tablicami zawierającymi mniej niż 14 elementów, można bezpiecznie rozważyć, że nie będzie żadnego odchylenia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-25 07:41:05
Nowoczesne Krótkie rozwiązanie inline wykorzystujące funkcje ES6:
['a','b','c','d'].map(x => [Math.random(), x]).sort(([a], [b]) => a - b).map(([_, x]) => x);
(dla celów edukacyjnych)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 18:14:29
Prosta modyfikacja odpowiedzi CoolAJ86 które nie modyfikują oryginalnej tablicy
/**
* Returns a new array whose contents are a copy shuffled of the array.
* @param {Array} a 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 remain elements to shuffle...
while (currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = newArray[currentIndex];
newArray[currentIndex] = newArray[randomIndex];
newArray[randomIndex] = temporaryValue;
}
return newArray;
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-20 07:06:21
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-21 06:31:07
Randomize array using 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]));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-27 15:51:32
Randomize array
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;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-07 07:51:52
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
}
};
Po prostu przekaż tablicę do funkcji i w zamian uzyskaj tablicę tasowaną
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-23 03:47:00