【Javascript】配列の順序のランダム入れ替え
問題
phpだと shuffle($array)で配列の内容をランダムな順序に入れ替えられるじゃないですか。
Javascriptでも配列の要素のランダム入れ替えってできる?
[0,1,2,3,4,5,6,7,8,9] → [4,6,8,0,9,3,7,1,2] のような感じ。
答え
shuffle()関数で配列の要素をシャッフルできるのは、便利機能満載、関数の塊のphpならではの風景。
JavascriptのArrayオブジェクトにshuffleはない。実装方法も考えて自分で作る必要がある。
乱数で重みをつけて並べ替える方法
var x = [0,1,2,3,4,5,6,7,8,9];
//配列xの各要素に乱数で重みをつける
for (var i = 0, l = x.length; i < l; ++i) {
x[i] = [x[i], Math.random()];
}
//配列xを重みによってソートする
x.sort(function(a, b){return a[1] - b[1];});
//配列xを元の形に戻したいので、重み部分のデータを取り除く
for (var i = 0, l = x.length; i < l; ++i) {
x[i] = x[i][0];
}
//xの要素はランダムな順序に入れ替えられた
alert(x);
シュワルツ変換というらしい。
Javascript1.6以降で、Array.mapメソッドがあれば1行で書ける。
var x = [0,1,2,3,4,5,6,7,8,9]
x = x.map(function(a){return {weight:Math.random(), value:a}})
.sort(function(a, b){return a.weight - b.weight})
.map(function(a){return a.value});
alert(x);
var x = [0,1,2,3,4,5,6,7,8,9]
x = x.map(function(a){return [a, Math.random()]})
.sort(function(a, b){return a[1] - b[1]})
.map(function(a){return a[0]});
alert(x);
Arrayのメソッドとして x.shuffle() のような呼び出し方をしたい場合は、以下のようにする。
Array.prototype.shuffle = function() {
return this.map(function(a){return [a, Math.random()]})
.sort(function(a, b){return a[1] - b[1]})
.map(function(a){return a[0]});
}
var x = [0,1,2,3,4,5,6,7,8,9];
alert(x.shuffle());
Fisher-Yatesというアルゴリズムを使った例
Array.prototype.shuffle = function() {
var i = this.length;
while(i){
var j = Math.floor(Math.random()*i);
var t = this[--i];
this[i] = this[j];
this[j] = t;
}
return this;
}
var x = [0,1,2,3,4,5,6,7,8,9];
x.shuffle();
alert(x);
ランダム番目を取り出していく方法
Array.prototype.shuffle = function(){
var l = this.length;
var a = this.concat();
var r = [];
while(l) r.push(a.splice(Math.floor(Math.random() * l--), 1));
return r;
}
var x = [0,1,2,3,4,5,6,7,8,9];
y = x.shuffle();
alert(y);