JavaScript

最終更新日:
公開日:

レシピ

配列

配列の要素の並びをシャッフルする

配列の要素の並びをランダムに並び替える方法について解説します。

この記事のポイント

  • 要素の並びをシャッフルするときに使う乱数はMath.randomメソッドMath.floorメソッドを組み合わせて取得する
  • 今回解説する方法は配列の添字(インデックス)が数値の場合のみシャッフルできる

目次

配列の要素をランダムに並び替える

配列の要素をランダムに並び替えてシャッフルするときは、ランダムな数値を取得するMath.randomメソッドと小数点を切り捨てるMath.floorメソッドを組み合わせて実現することができます。

以下のコード例では、配列をランダムに並び替えるarrayShuffle関数を用意して、引数で受け取った配列の並びを直接編集します。

JS コード例

function arrayShuffle(array) {
  for(let i = (array.length - 1); 0 < i; i--){

    // 0〜(i+1)の範囲で値を取得
    let r = Math.floor(Math.random() * (i + 1));

    // 要素の並び替えを実行
    let tmp = array[i];
    array[i] = array[r];
    array[r] = tmp;
  }
  return array;
}

let numbers = [ 1, 2, 3, 4, 5];

// 配列を5回シャッフルする
for(let i=0; i < 5; i++) {
  console.log(arrayShuffle(numbers));
}
// 1回目:(5) [1, 4, 5, 2, 3]
// 2回目:(5) [1, 2, 4, 5, 3]
// 3回目:(5) [2, 4, 3, 1, 5]
// 4回目:(5) [5, 2, 3, 1, 4]
// 5回目:(5) [1, 4, 3, 5, 2]

以降はarrayShuffleメソッドの内容を解説していきます。

配列をランダムに並び替える仕組み

最初に、引数arrayで並び替える配列を受け取って、for文で「array.length – 1」で配列の長さから1引いた値を変数iに取得します。
今回は用意した配列の長さが5なので、iには4が入ります。

続いて、今回のポイントになる乱数を取得して変数rに入れます。

Math.randomメソッド0〜1未満の範囲で数値をランダムに取得することができます。
そこへ「i+1」の値を掛けることで、0〜5未満(未満なので0〜4の間)の浮動小数点数を取得します。
以下のコードで、この乱数を作成する部分だけを抜き出して実行してみましょう。

JS コード例

for(let i=4; 0 < i; i--) {
	console.log( Math.random() * (i + 1) );
}
// 1回目:1.4268779798727227
// 2回目:3.847236648430684
// 3回目:2.741736294824827
// 4回目:0.8824344717307855

同じコードをもう1回実行してみます。

JS コード例

for(let i=4; 0 < i; i--) {
	console.log( Math.random() * (i + 1) );
}
// 1回目:4.975897478554402
// 2回目:1.449651515419105
// 3回目:2.735562906724822
// 4回目:1.5841041797972597

全く異なる数値を取得できることが確認できました。
小数点以下の桁数が多いですが、0〜5未満の間でランダムな数値を取得できています。

続いて、Math.floorメソッドを使って小数点以下を切り捨てます。
結果として、以下のように整数になったランダム値を取得することができます。

JS コード例

for(let i=4; 0 < i; i--) {
	console.log( Math.floor(Math.random() * (i + 1)) );
}
// 1回目:4
// 2回目:1
// 3回目:2
// 4回目:1

ここまでで、0から配列の長さの間の数値を変数rに取得することができるようになりました。

for文でループ処理を繰り返すとiの値が1ずつ少なくなっていくため、今回の例では1回目のループは0〜5未満の間のランダムな整数、2回目のループは0〜4未満の整数、3回目のループは0〜3未満とループを繰り返すごとに範囲が狭くなっていく仕組みです。

次のコードの箇所で、いよいよ配列の要素の並び替えを実行します。

JS コード例

let tmp = array[i];
array[i] = array[r];
array[r] = tmp;

1行目は、配列の末尾から要素を1つ取り出して、変数tmpに値を一時的に保持しておきます。
2行目の「array[i] = array[r];」で、先ほど取得したランダムな整数を使って配列の末尾に要素を1つ移動します。
最後に、先ほど一時保持した値をarray[r]に入れて1回目の置き換えを完了します。

この置き換えを、i0より大きい間繰り返します。
上記のコード例ではi4が入るため、4回の置き換えを実行します。

3つの異なる配列を使って要素の並びをシャッフルする

続いて、上記のarrayShuffleメソッドをそのまま使って3つの異なるタイプの配列で要素の並びをシャッフルしてみましょう。

タイプ1は要素の長さが10個のケース、タイプ2は要素に文字列が入っているケース、タイプ3は要素にオブジェクトが入っているケースでそれぞれ並びをシャッフルして、console.logメソッドで配列の内容を出力します。

JS コード例

// タイプ1:長さが10の配列
let numbers2 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9];
arrayShuffle(numbers2);
console.log(numbers2);
// (9) [9, 1, 3, 7, 5, 6, 2, 4, 8]


// タイプ2:要素が文字列の配列
let animals = [ "tiger", "bear", "pig"];
arrayShuffle(animals);
console.log(animals);
// (3) ["bear", "pig", "tiger"]


// タイプ3:要素がオブジェクトの配列
let menu = [
  {
    id: 1001,
    name: "coffee beans",
    price: 500
  },
  {
    id: 1002,
    name: "cup",
    price: 780
  },
  {
    id: 1003,
    name: "scone",
    price: 300
  },
];
arrayShuffle(menu);
console.log(menu);
// 0: {id: 1003, name: "scone", price: 300}
// 1: {id: 1002, name: "cup", price: 780}
// 2: {id: 1001, name: "coffee beans", price: 500}

それぞれのパターンをconsole.logメソッドで出力結果してみると、要素の並びをランダムにシャッフルできていることが確認できます。