HOWTO · TypeScript

TypeScript でオブジェクトの配列を並べ替える

この記事では、TypeScript でオブジェクトの配列を並べ替える方法を示します。

このページの内容

型付きオブジェクトの配列は、employeesList.sort((a, b) => a.empId - b.empId) で並べ替えられます。比較関数が負の数を返すと a が先になり、正の数を返すと b が先になります。比較する値が等しい場合は 0 を返します。降順にするには減算の順序を逆にし、最初のキーが同じ場合は別のプロパティで比較します。sort() は元の配列を変更します。元の順序を保つには、先にスプレッド構文で新しい配列を作成します。

レコードのオブジェクト型を定義する

インターフェースでは、各レコードに必要なプロパティを定義します。ここでは、各従業員が数値の empId と文字列の empDesignation を持ちます。共通の型を使うと、配列と比較関数で使うプロパティ名の両方を TypeScript でチェックできます。このインターフェースはコンパイル時の契約です。編集中のプロパティ名の誤りを見つける助けになりますが、外部から受け取ったデータを実行時に検証するものではありません。比較関数で使う値に合わせて、プロパティの型を指定してください。

TypeScript でオブジェクトの配列を作成する

配列を Employee[] として宣言すると、各要素がインターフェースに適合する必要があります。TypeScript では、interface Employee { empId: number; empDesignation: string } を定義し、const employeesList: Employee[] = [...] と宣言します。サンプルには empId が同じ従業員が 2 人含まれており、最後の比較関数では職位が第 2 のキーとして役立ちます。データと並べ替えコールバック内のプロパティ名は、完全に一致させてください。各オブジェクトリテラルは Employee に照らしてチェックされるため、必須プロパティの省略や型の異なる値は型チェック時に報告されます。下の実行例では Node.js でそのまま実行できる JavaScript 互換のオブジェクトリテラルを使っています。TypeScript の型注釈は .ts ファイルに記述してください。

1つ以上のプロパティでオブジェクトを並べ替える

数値の比較関数 a.empId - b.empId は ID を昇順に並べ替え、値が同じ場合は 0 を返します。降順にするには b.empId - a.empId を使います。2つ目のプロパティでも並べ替える場合は、ID の比較結果が 0 でなければその値を返し、ID が同じときに empDesignation を比較します。両方のキーが同じレコードに対しては、比較関数が 0 を返す必要があります。同値の場合に常に -1 を返すと、並べ替えアルゴリズムに一貫しない順序規則を与えることがあります。ほかの文字列フィールドでは、減算ではなく文字列比較を使ってください。人間の言語に合わせた順序が必要な場合は localeCompare() が便利です。結果はロケールによって変わることがあるため、地域ごとの順序を一定にしたい場合はロケールを明示してください。プロパティが存在しない可能性がある場合は、値を比較する前に、そのレコードをどの位置に置くか決めて処理します。

次の例を実行します。

const employeesList = [
  { empId: 20, empDesignation: "senior engineer" },
  { empId: 14, empDesignation: "junior engineer" },
  { empId: 14, empDesignation: "developer" },
  { empId: 25, empDesignation: "program manager" },
  { empId: 12, empDesignation: "director" },
];

const byIdAscending = [...employeesList].sort((a, b) => a.empId - b.empId);
const byIdDescending = [...employeesList].sort((a, b) => b.empId - a.empId);
const byIdThenDesignation = [...employeesList].sort((a, b) =>
  a.empId - b.empId || a.empDesignation.localeCompare(b.empDesignation)
);

console.log(byIdAscending.map((employee) => employee.empId).join(", "));
console.log(byIdDescending.map((employee) => employee.empId).join(", "));
console.log(byIdThenDesignation.map((employee) => `${employee.empId}: ${employee.empDesignation}`).join(" | "));
12, 14, 14, 20, 25
25, 20, 14, 14, 12
12: director | 14: developer | 14: junior engineer | 20: senior engineer | 25: program manager

スプレッド構文を使うことで、各並べ替えはコピーに対して行われ、employeesList は宣言時の順序のまま保たれます。最初の2行には ID が逆方向の順序で表示されます。最後の行には各 ID と職位が表示され、ID が同じ従業員に限って職位で比較されます。実際のアプリケーションでは、同順位のレコードを区別するのに適したプロパティを第 2 のキーに選んでください。必要に応じて、同じ方法で比較を追加できます。