HOWTO · JavaScript

在 JavaScript 中按屬性對物件陣列進行排序

本教程演示瞭如何按某些屬性對物件陣列進行排序。

本頁內容

若要依物件的某個屬性排序陣列,請將比較函式傳給 sort()。比較函式會讀取兩個物件的該屬性;第一個物件應排在前面時回傳負數,應排在後面時回傳正數,鍵值相等時則回傳零。字串鍵使用字串比較,數值鍵則使用相減的方式比較。

範例中的程式碼與輸出維持英文。

依字串屬性排序物件陣列

比較前可以先將兩個字串正規化。這會讓範例不區分大小寫,同時保留物件中原本的 lastName 值。

執行以下範例:

本節中的程式碼以及顯示的標籤或輸出仍為英文。

const students = [
  { firstName: 'Rohan', lastName: 'Dalal', age: 19 },
  { firstName: 'Zain', lastName: 'Ahmed', age: 17 },
  { firstName: 'Anadi', lastName: 'Malhotra', age: 19 }
];

students.sort((a, b) => {
  const left = a.lastName.toLowerCase();
  const right = b.lastName.toLowerCase();
  if (left < right) return -1;
  if (left > right) return 1;
  return 0;
});

console.log(students.map(student => student.lastName).join(', '));
Ahmed, Dalal, Malhotra

比較函式會回傳 sort() 所需的排序訊號;不必恰好回傳 -1 或 1,只要回傳負值、零或正值即可。若不希望大小寫影響順序,將字串轉成小寫會很有用。這不會改變儲存的姓名,因為 toLowerCase() 會回傳新的字串。

使用 localeCompare() 排序字串

對字串屬性而言,localeCompare() 能簡潔地作為比較函式,並遵循語言相關的排序規則。它會回傳負數、零或正數,因此可直接用於 sort():

本節中的程式碼以及顯示的標籤或輸出仍為英文。

const students = [
  { firstName: 'Rohan', lastName: 'Dalal', age: 19 },
  { firstName: 'Zain', lastName: 'Ahmed', age: 21 },
  { firstName: 'Anadi', lastName: 'Malhotra', age: 16 }
];

students.sort((a, b) => a.lastName.localeCompare(b.lastName));
console.log(students.map(student => student.lastName).join(', '));
Ahmed, Dalal, Malhotra

當鍵值是文字,而且適合依語系規則比較時,請使用這種方式。localeCompare() 比較的是字串,並非數值排序方法。若要明確指定語言,或設定區分大小寫等選項,請將執行環境支援的語系與選項傳給 localeCompare()。

依數值屬性排序

用第一個物件的數值鍵減去第二個物件的數值鍵。若第一個年齡較小,a.age - b.age 會是負數,因此升冪排序時 a 會排在 b 前面。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

const students = [
  { firstName: 'Rohan', lastName: 'Dalal', age: 19 },
  { firstName: 'Zain', lastName: 'Ahmed', age: 21 },
  { firstName: 'Anadi', lastName: 'Malhotra', age: 16 }
];

students.sort((a, b) => a.age - b.age);
console.log(students.map(student => student.age).join(', '));
16, 19, 21

這種相減方式適用於數值。不要用它比較姓名:字串相減無法表示字母順序。同樣地,不傳入比較函式也不會讓 sort() 檢查物件的某個屬性;預設排序會比較陣列元素轉成字串後的表示方式,因此物件通常需要明確指定比較函式。

以降冪排序

調換比較函式的運算元即可反轉排序方向。以數值年齡為例,b.age - a.age 會讓年齡較大者排在前面。如此一來,排序規則會直接對應所選屬性,也不必先按一個方向排序,再反轉結果陣列。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

const students = [
  { firstName: 'Rohan', lastName: 'Dalal', age: 19 },
  { firstName: 'Zain', lastName: 'Ahmed', age: 21 },
  { firstName: 'Anadi', lastName: 'Malhotra', age: 16 }
];

students.sort((a, b) => b.age - a.age);
console.log(students.map(student => student.age).join(', '));
21, 19, 16

若要將字串按降冪排序,可以反轉字串比較函式的結果,例如對 a.lastName.localeCompare(b.lastName) 的結果取負值。比較函式應保持一致,讓鍵值相等時仍回傳零。

sort() 的重要行為與限制

sort() 會就地修改陣列,並回傳同一個陣列。若要保留原始順序,請先用 const sortedStudents = [...students] 複製陣列,再排序副本。物件本身不會被複製,因此排序改變的是物件在陣列中的位置,而不是物件的屬性。

若未提供比較函式,sort() 會將值轉成字串後比較;因此預設排序不適合用於數值排序,也不會依物件的指定屬性排序。請提供符合鍵值型別的比較函式。這些範例假設每個物件都有指定的字串或數值屬性;範例未定義缺少鍵值或混合型別時的處理方式,因此套用比較函式前,請先驗證資料,或決定這些值應如何比較。

如需了解底層陣列 API,請參閱 sort() 方法參考。