跳至主要内容

JavaScript reduce 小練習

題目說明

你收到一筆餐廳的點餐紀錄資料,格式如下:

const orders = [
{ item: "Burger", quantity: 2 },
{ item: "Fries", quantity: 3 },
{ item: "Burger", quantity: 1 },
{ item: "Soda", quantity: 5 },
{ item: "Fries", quantity: 1 },
];

請撰寫一個函式 summarizeOrders(orders),輸出每種品項的總數量,格式如下:

{
Burger: 3,
Fries: 4,
Soda: 5
}

✅ 解法一:使用 forEach

const summarizeOrders = (orders) => {
const result = {};
orders.forEach(order => {
if (result[order.item]) {
result[order.item] += order.quantity;
} else {
result[order.item] = order.quantity;
}
});
return result;
};

console.log(summarizeOrders(orders));
// ➜ { Burger: 3, Fries: 4, Soda: 5 }

解法說明:

  1. 建立空物件 result 來存放結果
  2. 使用 forEach 遍歷每筆訂單
  3. 檢查該品項是否已存在於結果物件中
  4. 如果存在就累加數量,不存在就設定初始數量
  5. 回傳結果物件

✅ 解法二:使用 reduce

const summarizeOrders = (orders) => {
return orders.reduce((acc, curr) => {
if (acc[curr.item]) {
acc[curr.item] += curr.quantity;
} else {
acc[curr.item] = curr.quantity;
}
return acc;
}, {});
};

console.log(summarizeOrders(orders));
// ➜ { Burger: 3, Fries: 4, Soda: 5 }

解法說明:

  1. 使用 reduce 將陣列歸約成一個物件
  2. acc(累加器)初始值為空物件 {}
  3. 每次迭代檢查品項是否存在並累加數量
  4. 必須回傳 acc 給下次迭代使用

✅ 精簡寫法(推薦)

const summarizeOrders = (orders) =>
orders.reduce((acc, { item, quantity }) => {
acc[item] = (acc[item] || 0) + quantity;
return acc;
}, {});

console.log(summarizeOrders(orders));
// ➜ { Burger: 3, Fries: 4, Soda: 5 }

精簡技巧說明:

  1. 解構賦值{ item, quantity } 直接取出物件屬性
  2. 短路運算(acc[item] || 0) 如果 acc[item] 不存在則使用 0
  3. 一行解決:避免 if/else 判斷,代碼更簡潔

🔍 重要概念解析

短路運算技巧

// 這兩種寫法效果相同:

// 傳統寫法
if (acc[item]) {
acc[item] += quantity;
} else {
acc[item] = quantity;
}

// 短路寫法
acc[item] = (acc[item] || 0) + quantity;

運作原理:

  • 如果 acc[item] 存在且不為 falsy,使用原值
  • 如果 acc[item] 不存在或為 falsy,使用 0

🎯 延伸練習

練習 1:加入品項價格統計

const ordersWithPrice = [
{ item: "Burger", quantity: 2, price: 120 },
{ item: "Fries", quantity: 3, price: 60 },
{ item: "Burger", quantity: 1, price: 120 },
];

// 期望輸出:
// {
// Burger: { quantity: 3, totalPrice: 360 },
// Fries: { quantity: 3, totalPrice: 180 }
// }

解答:

const summarizeOrdersWithPrice = (orders) =>
orders.reduce((acc, { item, quantity, price }) => {
if (!acc[item]) {
acc[item] = { quantity: 0, totalPrice: 0 };
}
acc[item].quantity += quantity;
acc[item].totalPrice += quantity * price;
return acc;
}, {});

練習 2:找出最受歡迎的品項

const findMostPopular = (orders) => {
const summary = summarizeOrders(orders);
return Object.keys(summary).reduce((most, item) =>
summary[item] > summary[most] ? item : most
);
};

console.log(findMostPopular(orders)); // "Soda"