私はこのような配列を持っています:
var arr1 = ["a", "b", "c", "d"];
それをランダム化/シャッフルするにはどうすればいいですか?
事実上不偏シャッフルアルゴリズムはFisher-Yates(別名Knuth)シャッフルです。
https://github.com/coolaj86/knuth-shuffle を参照してください。
あなたは ここで/ - 素晴らしい視覚化を見ることができます (そして元の記事 これにリンクされた )
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);
もう少し情報 アルゴリズムについて used.
これは Durstenfeldシャッフル 、Fisher-Yatesのコンピュータ最適化バージョンのJavaScript実装です。
/**
* 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;
}
}
Fisher-Yatesアルゴリズムは、元の配列要素ごとに1つのランダム要素を選び、それを次の描画から除外することによって機能します。カードのデッキからランダムに選ぶのと同じです。
この除外は、選択された要素を現在の要素と交換してから、残りの要素から次のランダム要素を選択することによって(Durstenfeldによってコンピュータ用に考案された)巧妙な方法で行われます。効率を最適化するために、ランダムピックが単純化されるように(常に0から開始できます)ループが逆方向に実行され、他に選択肢がないため最後の要素をスキップします。
このアルゴリズムの実行時間はO(n)です。シャッフルはその場で行われることに注意してください。そのため、元の配列を変更したくない場合は、最初に.slice(0)
を使用してそのコピーを作成してください。
新しいES6では、2つの変数を同時に割り当てることができます。これは、2行の変数の値を入れ替えるときに特に便利です。コードを1行で実行できるからです。これは、この機能を使用した同じ機能の短い形式です。
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]];
}
}
[コミュニティ編集:この答えは間違っている。コメントを見てください。これは珍しいことではないので、今後の参考のためにここに残しておきます。
[1,2,3,4,5,6].sort(function() {
return .5 - Math.random();
});
Arrayのプロトタイプとして使用できます(または使用する必要があります)。
クリストファーから:
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;
}
Underscore.jsライブラリを使用してください。メソッド_.shuffle()
は、この場合に適しています。
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();
新しい!
より短く、おそらくより高速なFisher-Yatesシャッフルアルゴリズム
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
}
スクリプトサイズ(関数名としてfyを使用):90バイト
DEMOhttp://jsfiddle.net/vvpoma8w/
*おそらく、クロムを除くすべてのブラウザでより高速です。
ご不明な点がございましたらお尋ねください。
編集
はい、速いです
パフォーマンス:http://jsperf.com/fyshuffle
上位投票関数を使用します。
EDIT過剰な計算がありました(--c + 1は不要)、誰も気づきませんでした
短く(4バイト)&速く(テストしてください!)。
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
}
var rnd=Math.random
のどこかにキャッシュしてからrnd()
を使用すると、大きな配列のパフォーマンスがわずかに向上します。
http://jsfiddle.net/vvpoma8w/2/
読み取り可能なバージョン(元のバージョンを使用します。これは遅くなります。多分これを読んでください Javascriptコードを「縮小」する方法 ですが、上記のようなJavaScriptミニファイヤで次のコードを圧縮することはできません。)
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
}
}
Mapとsortを使えば簡単にできます。
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)
多相配列をシャッフルすることができます。ソートはMath.randomと同じくらいランダムで、ほとんどの目的にはこれで十分です。
要素は各反復で再生成されない一貫したキーに対してソートされ、各比較は同じ分布から引き出されるため、Math.randomの分布の乱数以外の部分は相殺されます。
小さな配列のための非常に簡単な方法は単にこれです:
const someArray = [1, 2, 3, 4, 5];
someArray.sort(() => Math.random() - 0.5);
おそらくあまり効率的ではありませんが、小さな配列ではこれで問題ありません。ここに例があるので、あなたはそれがどれほどランダムであるか(そうでないか)そしてそれがあなたのユースケースに合うかどうかを見ることができる。
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>
@Laurens Holstsの回答に追加します。これは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
};
ES2015ではこれを使うことができます。
Array.prototype.shuffle = function() {
let m = this.length, i;
while (m) {
i = (Math.random() * m--) >>> 0;
[this[m], this[i]] = [this[i], this[m]]
}
return this;
}
使用法:
[1, 2, 3, 4, 5, 6, 7].shuffle();
いくつかの答えはES6構文を使用して短くすることができます。
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
};
私は個人的には純粋で、比較的単純で、Google Chromeでの私のテストによれば(他の純粋なバージョンと比較して)最も効率的なのでこの機能を使っています。
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]]
}
}
このページでわかるように、過去にここで提供された不正確な解決策がありました。したがって、信頼性とパフォーマンスを考慮して、純粋な(副作用のない)配列ランダム化関数をテストするために次の関数を作成しました。私はこの答えで提示されたすべてのオプションをテストするためにそれを使いました。
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}`)
}
以下のどちらかを使用できます。
type GetShuffledArr= <T>(arr:Array<T>) => Array<T>
interface IGetShuffledArr{
<T>(arr:Array<T>): Array<T>
}
ES6純粋、再帰的
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))];
};
このバージョンは、反復純粋バージョンよりも効率的ではありません。
ES6 Pureで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]
})
}
このバージョンは、反復純粋バージョンよりもわずかに非効率的です。
ES6 Pureで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]
)
}
このバージョンは、反復純粋バージョンよりもわずかに非効率的です。
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;
};
私は、この質問の複製の「著者によって削除されました」という回答にこの変種がぶら下がっているのを見つけました。すでに多くの支持を得ている他の回答とは異なり、これは次のとおりです。
shuffled
ではなくshuffle
名)Array.prototype.shuffled = function() {
return this.map(function(n){ return [Math.random(), n] })
.sort().map(function(n){ return n[1] });
}
再帰的な解決策:
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));
};
Fisher-Yates javascriptでシャッフルする。 2つの効用関数(swapとrandInt)を使用すると、ここで他の答えと比較してアルゴリズムが明確になるので、これをここに投稿します。
function swap(arr, i, j) {
// swaps two elements of an array in place
var temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
function randInt(max) {
// returns random integer between 0 and max-1 inclusive.
return Math.floor(Math.random()*max);
}
function shuffle(arr) {
// For each slot in the array (starting at the end),
// pick an element randomly from the unplaced elements and
// place it in the slot, exchanging places with the
// element in the slot.
for(var slot = arr.length - 1; slot > 0; slot--){
var element = randInt(slot+1);
swap(arr, element, slot);
}
}
あなたは簡単にそれをすることができます:
// array
var fruits = ["Banana", "Orange", "Apple", "Mango"];
// random
fruits.sort(function(a, b){return 0.5 - Math.random()});
// out
console.log(fruits);
JavaScriptソート配列 を参照してください。
Update:ここでは、比較的simple(complexityパースペクティブ)およびshortアルゴリズムは小さなサイズの配列でも問題なく動作しますが、従来のよりも明らかにコストがかかります巨大な配列を扱う場合のDurstenfeldアルゴリズム。 Durstenfeldは、この質問に対するトップの回答の1つにあります。
元の答え:
シャッフル関数でソース配列を変更したくない場合、それをローカル変数にコピーしてから、残りは単純なシャッフルロジックで行います。
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;
}
シャッフルロジック:ランダムインデックスを選択し、対応する要素をresult配列に追加しますそして、ソース配列コピーから削除します。ソース配列がemptyを取得するまで、このアクションを繰り返します。
そして、あなたが本当にそれを短くしたいなら、ここに私が得ることができる距離があります:
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;
}
まず最初に、 ここ javascriptのさまざまなソート方法の視覚的な比較について見てください。
第二に、上のリンクをざっと見ると、random order
ソートは他の方法に比べて比較的うまく機能しているように見えますが、以下に示すように実装は非常に簡単で速いです。
function shuffle(array) {
var random = array.map(Math.random);
array.sort(function(a, b) {
return random[array.indexOf(a)] - random[array.indexOf(b)];
});
}
編集 :@gregersが指摘するように、compare関数はインデックスではなく値を使って呼び出されるので、indexOf
を使う必要があります。 indexOf
がO(n)時間内で実行されるため、この変更により大規模な配列にはコードがあまり適していないことに注意してください。
厳密モードを使用した、さらに別のFisher-Yatesの実装:
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;
}
他のすべての答えは高速ですが暗号レベルのランダム化には適していないMath.random()に基づいています。
以下のコードは、 暗号レベルのランダム化 にFisher-Yates
を利用しながら、よく知られているWeb Cryptography API
アルゴリズムを使用しています。
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));
function shuffle(array) {
array.sort(() => Math.random() - 0.5);
}
let arr = [1, 2, 3];
shuffle(arr);
alert(arr);
パイに指を入れるだけです。ここで私はFisher Yatesシャッフルの再帰的実装を提示します(私は思う)。それは一様なランダム性を与えます。
注:~~
(二重ティルド演算子)は、実際には正の実数に対してMath.floor()
のように振る舞います。ちょっと近道です。
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])));
CoolAJ86の answer を単純に変更したもので、元の配列は変更されません。
/**
* 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;
};
すでにいくつかの実装方法が推奨されていますが、forEachループを使用すると短く簡単にできるので、配列の長さの計算について心配する必要はなく、一時変数を使用しなくても大丈夫です。
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)
変わらない再帰的な答えはありませんでした。
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);
最短の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;
}
理論的な観点から、それを行う最もエレガントな方法は、私の謙虚な意見では、singleの間の乱数を取得することですおよびn!-1および{0, 1, …, n!-1}
から(0, 1, 2, …, n-1)
のすべての順列への1対1マッピングを計算します。大きなバイアスをかけずにそのような数値を取得するのに十分な信頼性のある(擬似)乱数ジェネレーターを使用できる限り、他のいくつかの乱数を必要とせずに目的を達成するのに十分な情報があります。
IEEE754倍精度浮動小数点を使用して計算する場合、ランダムジェネレーターで約15桁の小数が得られることが期待できます。15!= 1,307,674,368,000(13桁)があるため、最大15個の要素を含む配列で次の関数を使用でき、配列に大きなバイアスがないと仮定できます。最大14個の要素が含まれます。このシャッフル操作を何度も計算する必要がある固定サイズの問題に取り組んでいる場合は、次のコードを試してください:mayMath.random
は1回だけです(ただし、複数のコピー操作が含まれます)。
次の関数は使用されませんが、とにかくそれを提供します。このメッセージで使用される1対1のマッピング(順列を列挙するときに最も自然なマッピング)に従って、(0, 1, 2, …, n-1)
の指定された順列のインデックスを返します。最大16個の要素を処理することを目的としています。
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);
}
前の関数の逆数(独自の質問に必要)は以下のとおりです。最大16個の要素を使用することを目的としています。 (0, 1, 2, …, s-1)
の順序nの順列を返します。
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;
}
今、あなたがただ欲しいのは:
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]; });
}
わずかな理論的偏りのある最大16の要素で機能するはずです(ただし、実用的な観点からは気づきません)。 15の要素に対して完全に使用可能と見なすことができます。 14個未満の要素を含む配列を使用すると、偏りがないことを安全に考慮することができます。
ES6機能を使用した最新の短いインラインソリューション:
['a','b','c','d'].map(x => [Math.random(), x]).sort(([a], [b]) => a - b).map(([_, x]) => x);
(教育目的のため)
shuffle-array moduleを使用すると、アレイをシャッフルできます。これがその簡単なコードです。
var shuffle = require('shuffle-array'),
//collection = [1,2,3,4,5];
collection = ["a","b","c","d","e"];
shuffle(collection);
console.log(collection);
お役に立てれば。
他の解決策に従って、 in loco または新しい不変配列に適用することを検討すると、次のような実装が可能です。
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;
};
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;
}
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]));
ランダムにプッシュまたはシフト解除します(最初に追加します)。
['a', 'b', 'c', 'd'].reduce((acc, el) => {
Math.random() > 0.5 ? acc.Push(el) : acc.unshift(el);
return acc;
}, []);
私は誰もまだ配列プロトタイプを拡張しない間に連結することができる解決策を与えていないと思う( 悪い習慣 )あまり知られていないreduce()
を使うと、連結を可能にする方法で簡単にシャッフルを行うことができます。
var randomsquares = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle).map(n => n*n);
空の配列に対してこれを実行しようとすると失敗するので、おそらく2番目のパラメータ[]
を渡したいでしょう。
// 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);
shuffle
を次のように定義しましょう。
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;
}
あなたはそれをアクションJSFiddleまたはここで見ることができます
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));
}
ロナルドフィッシャーとフランクイェイツがシャッフル
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に最適化された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;
}
ランダム配列
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;
私はコンソールに貼り付けるonelinerについて考えていました。 .sort
のトリックはすべて間違った結果をもたらしていました。これが私の実装です:
['Bob', 'Amy', 'Joy'].map((person) => `${Math.random().toFixed(10)}${person}`).sort().map((person) => person.substr(12));
しかし、本番環境のコードでは使用しないでください。最適ではなく、文字列でのみ機能します。
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]));
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
}
};
配列をfunctionに渡すだけで、代わりにシャッフルされた配列を取得
// 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];
})
}
あまり才能はないがlodashの不思議にアクセスできる私たちにとっては、 lodash.shuffle などがあります。
d3.js は、 Fisher – Yatesシャッフル の 組み込み バージョンを提供します。
console.log(d3.shuffle(["a", "b", "c", "d"]));
<script src="http://d3js.org/d3.v5.min.js"></script>
d3.shuffle(array [、lo [、hi]]) <>
Fisher – Yatesシャッフル を使用して、指定された配列の順序をランダム化します。
配列全体を1つずつ再構築し、各要素をランダムな場所に配置します。
[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);
Fisher-Yatesのこのバリエーションは、要素をそれ自身と交換することを回避するため、わずかに効率的です。
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;
}
私は自分でシャッフル機能を書きました。ここでの違いはそれが値を繰り返すことは決してないということです(これのためにコードをチェックインします):
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, 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
})
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])
$=(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());
文字列の配列をシャッフルする:
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;
}