Skip to main content

對 array 進行排序或分組

第一部分:對陣列進行排序(Sorting)

排序的意思是將陣列中的元素依據某個規則排列,通常是從小到大(或大到小)。JavaScript 內建的 sort() 方法可以輕鬆做到這件事,但要注意:如果陣列是數字,sort() 預設會當成字串排序,所以會出錯(例如 [10, 2] 會變成 ['10', '2'],排序後還是 [10, 2] 但實際上是字串)。我們需要提供一個比較函式(comparison function)來修正。

步驟 1:準備一個簡單的數字陣列

先建立一個陣列,裡面放一些數字。打開瀏覽器 Console,輸入以下完整程式碼,按 Enter 執行,看看結果。

// 步驟 1:建立一個數字陣列
let numbers = [5, 2, 9, 1, 5, 6];

// 印出原始陣列,確認內容
console.log("原始陣列:", numbers);

執行後,你會看到輸出:原始陣列: [5, 2, 9, 1, 5, 6]。這是你的起點。

步驟 2:使用 sort() 進行升序排序(從小到大)

現在,我們用 sort() 方法,加上一個比較函式。比較函式是個小函式,接收兩個參數 a 和 b,如果 a - b 小於 0,就把 a 排在前面(升序)。

輸入以下完整程式碼(接續上面的 numbers 陣列):

// 步驟 2:升序排序(從小到大)
numbers.sort(function(a, b) {
return a - b; // 如果 a < b,回傳負數,a 排前面
});

// 印出排序後的陣列
console.log("升序排序後:", numbers);

執行後,輸出會是:升序排序後: [1, 2, 5, 5, 6, 9]。恭喜!你的陣列現在是排序好的。如果有重複數字(如兩個 5),它們會保持原相對位置。

步驟 3:使用 sort() 進行降序排序(從大到小)

如果想從大到小排序,只要把比較函式改成 b - a 就好。

輸入以下完整程式碼(你可以重設 numbers 陣列,或直接用上面的結果繼續):

// 先重設陣列(如果需要)
let numbersDesc = [5, 2, 9, 1, 5, 6];

// 降序排序(從大到小)
numbersDesc.sort(function(a, b) {
return b - a; // 如果 b < a,回傳負數,b 排前面
});

// 印出排序後的陣列
console.log("降序排序後:", numbersDesc);

輸出:降序排序後: [9, 6, 5, 5, 2, 1]。簡單吧?記住,sort() 會直接修改原陣列,如果你不想改原陣列,可以先用 slice() 複製一份:let copy = numbers.slice().sort(...);。

步驟 4:排序字串陣列或物件陣列

如果陣列是字串,sort() 預設就 OK(依字典順序)。如果是物件陣列(如人名和年齡),我們可以指定排序的屬性。

範例:排序物件陣列,按年齡升序。

// 步驟 4:物件陣列排序
let people = [
{ name: "小明", age: 25 },
{ name: "小華", age: 30 },
{ name: "小美", age: 20 }
];

// 按年齡升序排序
people.sort(function(a, b) {
return a.age - b.age; // 比較 age 屬性
});

// 印出排序後
console.log("按年齡排序:", people);

輸出會是按年齡 20, 25, 30 的順序。這樣你就能處理更複雜的資料了。

第二部分:對陣列進行分組(Grouping)

分組的意思是根據某個條件,將陣列元素分成幾個小組(像是分類)。JavaScript 沒有內建的 groupBy 方法(直到 ECMAScript 2023 才有,但為了相容性,我們用 reduce() 方法手動實現)。reduce() 就像是把陣列「歸約」成一個物件,key 是分組條件,value 是該組的子陣列。

步驟 1:準備一個可分組的陣列

我們用數字陣列,按奇偶分組。輸入以下程式碼:

// 步驟 1:建立陣列
let numbersGroup = [1, 2, 3, 4, 5, 6, 7, 8];

// 印出原始陣列
console.log("原始陣列:", numbersGroup);

輸出:原始陣列: [1, 2, 3, 4, 5, 6, 7, 8]。

步驟 2:使用 reduce() 按奇偶分組

我們建立一個空物件 groups,用 reduce() 遍歷陣列。如果數字是奇數,放進 odd 組;偶數放進 even 組。

輸入以下完整程式碼:

// 步驟 2:按奇偶分組
let groups = numbersGroup.reduce(function(accumulator, current) {
// accumulator 是累積的結果(物件),current 是當前元素

if (current % 2 === 0) {
// 偶數:如果 accumulator.even 不存在,先建立空陣列
if (!accumulator.even) {
accumulator.even = [];
}
accumulator.even.push(current);
} else {
// 奇數:同上
if (!accumulator.odd) {
accumulator.odd = [];
}
accumulator.odd.push(current);
}

return accumulator; // 回傳更新後的物件
}, {}); // 初始值是空物件 {}

// 印出分組結果
console.log("分組結果:", groups);
console.log("奇數組:", groups.odd);
console.log("偶數組:", groups.even);

執行後,輸出:

分組結果: { odd: [1, 3, 5, 7], even: [2, 4, 6, 8] }
奇數組: [1, 3, 5, 7]
偶數組: [2, 4, 6, 8]

解釋一下:

  • reduce() 的第一個參數是 callback 函式:accumulator 是之前累積的結果,current 是當前數字。

  • % 2 === 0 是檢查偶數(餘數 0)。

  • push() 把元素加到對應陣列。

  • 初始值 確保從空物件開始。

步驟 3:分組物件陣列(例如按年齡區間分組)

更實用的範例:按年齡分組成「年輕」(<30)「中年」(30-50)「老年」(>50)

// 步驟 3:物件陣列分組
let peopleGroup = [
{ name: "小明", age: 25 },
{ name: "小華", age: 35 },
{ name: "小美", age: 20 },
{ name: "阿姨", age: 55 },
{ name: "叔叔", age: 45 }
];

// 分組函式
let ageGroups = peopleGroup.reduce(function(accumulator, person) {
let groupKey;

if (person.age < 30) {
groupKey = "年輕";
} else if (person.age >= 30 && person.age <= 50) {
groupKey = "中年";
} else {
groupKey = "老年";
}

// 如果該組不存在,建立空陣列
if (!accumulator[groupKey]) {
accumulator[groupKey] = [];
}

// 加入人
accumulator[groupKey].push(person);

return accumulator;
}, {});

// 印出分組結果
console.log("年齡分組:", ageGroups);

輸出會是像這樣:

年齡分組: {
年輕: [{ name: '小明', age: 25 }, { name: '小美', age: 20 }],
中年: [{ name: '小華', age: 35 }, { name: '叔叔', age: 45 }],
老年: [{ name: '阿姨', age: 55 }]
}

這樣你就完成了分組!如果你的瀏覽器支援最新 JavaScript(ES2023),也可以用 groupBy() 方法簡化,但為了安全,我們用 reduce() 比較通用。