JavaScript約4分

配列を並べ替える前に元データを残す:元の順序と表示用の順序を分ける

sortを使うと、元の配列の順序も変わります。架空の作業時間の一覧を題材に、コピーしてから数値を並べ替える例を作り、元の順序・昇順・降順をそれぞれ確認します。

この記事の目次
  1. sortの戻り値を別名に入れるだけでは残らない
  2. 表示用の配列を作ってから並べ替える
  3. コピーできた範囲を言葉にする
  4. 値を変え、予想と出力を照合する

作業時間を短い順に並べた後、「入力した順に戻したい」と思ったら、元の配列も並び替わっていた。配列を並べ替える前に元データを残すには、元の配列と表示用の配列を分けます。まずは画面へ描画せず、コンソールの値で違いを確かめましょう。

ここでは架空の練習記録として、三つの作業時間を分で扱います。実際の受講者の記録ではありません。入力順を残す配列と、短い順に見る配列を作り、どちらをいつ使うか説明できることを目標にします。

sortの戻り値を別名に入れるだけでは残らない

次のコードは、起こりがちな問題を観察するための例です。ブラウザーのコンソールかNode.jsで実行できます。

const original = [25, 5, 100];
const sorted = original.sort((a, b) => a - b);
console.log(original.join(", ")); // 5, 25, 100
console.log(sorted === original); // true

別の変数名へ代入しても、この二つは同じ配列を指しています。元の入力順である25、5、100は、この配列の中には残っていません。変数を増やすことと、配列を複製することを分けて考えます。

MDNのsortの説明では、元の配列を変更する動作を確認できます。また、比較関数を省略した並べ替えは数値の大小順とは限りません。今回は数値だけの配列とし、比較関数を明示します。

表示用の配列を作ってから並べ替える

こちらが修正例です。前の例とは変数名を変えているので、続けて実行できます。

const durations = [25, 5, 100];
const ascending = [...durations].sort((a, b) => a - b);
const descending = [...durations].sort((a, b) => b - a);
console.log(durations.join(", ")); // 25, 5, 100
console.log(ascending.join(", ")); // 5, 25, 100
console.log(descending.join(", ")); // 100, 25, 5
console.log(ascending === durations); // false

角括弧とスプレッド構文で新しい配列を作り、その新しい配列へsortを呼び出しています。昇順と降順を、それぞれ元のdurationsから作る点にも注目してください。どの順序の配列から出発したかが読み取りやすくなります。

この例のa - bは、小さい数を前へ置く比較です。b - aでは逆の順序になります。文字列や未入力の値が混ざったケースは扱っていないので、フォーム入力を使う場合は、値を数値として受け取れているかを先に確かめます。

コピーできた範囲を言葉にする

今回の配列の中身は数値です。新しい配列を並べ替えても、元の配列の順序は変わりません。ただし、この書き方は中に入ったオブジェクトまで深く複製するものではありません。

将来、作業名やメモを持つオブジェクトの一覧に変えた場合、新しい配列からオブジェクトのプロパティを書き換えると、元の配列から見える値も変わることがあります。「何でも完全なバックアップになる」とは考えず、今回保っているのは配列の並び順だと説明してください。

項目を条件で選び出す処理はfilterで一覧を絞る記事で扱っています。選別と並べ替えを一度に書く前に、各段階でどの配列が残るかを確かめると、原因を追いやすくなります。

値を変え、予想と出力を照合する

最後にdurationsを[10, 2, 10, 1]へ変えます。実行前に、元の順序、昇順、降順の三つを紙に書きます。実行結果と比べ、同じ数が二つあっても項目が減っていないか確認しましょう。

空の配列でも試し、三つとも空のまま扱えることを見ます。今回はエラー表示や画面の更新は作りません。無料レッスンの後に取り組む小さな練習として、まず元の配列を保ったまま二種類の順序を出せれば完了です。

記事についてのお問い合わせ

記載内容へのご質問や訂正のご連絡は、hello@junkbranding.comまでお願いします。

← 記事一覧に戻る