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 相同,因此最後的比較函式可以用職稱作為第二個排序鍵。資料中的屬性名稱必須與排序回呼中的名稱完全一致。每個物件字面值都會依照 Employee 檢查;若缺少必要屬性或值的型別不符,型別檢查時就會指出問題。下方的可執行範例使用與 JavaScript 相容的物件字面值,因此可直接在 Node.js 執行;TypeScript 型別標註則應放在 .ts 原始檔中。
依一個或多個屬性排序物件
數值比較函式 a.empId - b.empId 會依 empId 升冪排序,值相同時也會自然回傳 0。若要依降冪排序,請使用 b.empId - a.empId。若要再依第二個屬性排序,先在 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 仍維持宣告時的順序。前兩行會以相反方向顯示 ID。最後一行會顯示每位員工的 ID 與職稱;只有 ID 相同的員工才會再比較職稱。在實際應用程式中,請選擇能讓相同排序值的記錄仍有意義的第二個屬性;需要時也可以用相同方式加入更多比較條件。