JavaScriptでシャッフル&ソート
JavaScript でシャッフルしたい!
ビンゴボール、トランプカードなどのシャッフル。
JavaScript で配列をシャッフルする方法です。
順を追って解説しているので、実装方法だけを知りたい人は「シャッフルしてみる」までスキップしてください。
シャッフルの前に知っておくこと、それは sort
シャッフル実装の前にソートを勉強しましょう。
並びをランダムにしたいシャッフルとは真逆の機能ですが、配列のソート機能を使ってシャッフルを実現します。
Array.prototype.sort
Array
のプロトタイプにある、sort
メソッド。
これは配列内部を直接並び替えます。
コピーを作成するわけではないことに注意してください。
// 配列にソートされていない数字を用意
const array = [3, 9, 1, 2, 4, 5, 6, 7, 8, 10];
// sortメソッドを実行すると、配列の中身を直接操作します
array.sort();
// 結果: [ 1, 10, 2, 3, 4, 5, 6, 7, 8, 9 ]
console.log(array);
さて、上記の結果を見てみると、1
の次は10
になっていますね。
これはsort
メソッドでは文字列としてソートされるためです。
Number で入れているのに。。。
sort には関数を渡せる
数字として比較し、1
の次は2
になってほしいですね。
sort
メソッドには関数を渡せるので、これで結果を変えることができます。
// 配列にソートされていない数字を用意
const array = [3, 9, 1, 2, 4, 5, 6, 7, 8, 10];
// 並び替えルールを関数で提供
array.sort((a, b) => a - b);
// 結果: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
console.log(array);
sort
メソッドに渡す関数は、比較した結果の大小を数字で表現して返す必要があります。
a
とb
の2つを比較したとき、a
が大きければ0より大きい
数字を、b
が大きければ0未満
の数字、等しければ0
を返すようにします。
このサンプルではa
からb
を引き算した結果を返しています。
これで数字順にソートされた結果を得ることができました。
シャッフルしてみる
上の例から、シャッフルするにはランダムに正の値と負の値を返せばシャッフルできそうです。
JavaScript にはMath
オブジェクトにrandom
関数があり、0〜1 未満の数をランダムに返してくれます。
そのまま使うと 0 未満の数字は出せないので、-0.5
して負の数も返すようにします。
数字の比較はしないので、関数の引数a
とb
はなくても大丈夫です。
// 配列にソートされている数字を用意
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// ランダムに-0.5〜0.5の数字を返す
array.sort(() => Math.random() - 0.5);
console.log(array);
// 結果: [ 7, 3, 8, 2, 4, 6, 5, 1, 9, 10 ]
これで配列をシャッフルすることができました!
おまけ: 配列に shuffle メソッドを追加実装したい
シャッフルしたいのにsort
で呼び出すなんて、ちょっとややこしいですね。
配列のprototype
にshuffle
メソッドを実装してみましょう。これにより配列インスタンスからshuffle
メソッドを使用できるようになります。
// 配列にshuffleメソッドを追加
Array.prototype.shuffle = function () {
this.sort(() => Math.random() - 0.5);
}
// 配列にソートされている数字を用意
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// shuffleメソッドをコール
array.shuffle();
console.log(array);
// 結果: [ 5, 2, 1, 7, 9, 3, 6, 8, 10, 4 ]
ちゃんとshuffle
メソッドが追加されてシャッフルできましたね!