昨天在面試時突然被問到有沒有使用過 reduce,一時之間腦內跑馬燈走過,有聽過這個字但好像沒有實際使用過,於是模稜兩可的給了一個很爛的回答,讓人後悔至極,應該大方承認自己沒有相關使用經驗,至少還比較有臺階可下。不過也因為如此,讓我發現自己對這個陣列的操作方法還不熟,趕緊來補強一下。

Array.prototype.reduce()

根據 MDN 的說明,reduce 方法將一個累加器及陣列中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。其實這個描述挺寫實的,不過我們搭配實作來看會更清楚。

Syntax

array.reduce(function(accumulator, currentValue, currentIndex, array),initialValue)

其中有 4 個參數,分別代表不同的意思。

  • accumulator:累加總計
  • currentValue:目前值
  • currentIndex(optional):這一輪迭代的索引(index)
  • array(optional):陣列內容

initialValue 則是代表第一次要傳入的初始值

實例 1

const array = [1, 3, 4, 5]
const arrayReduced = array.reduce((accumulator, currentValue) => {
  return accumulator + currentValue
}, 5)   //初始值為 5

console.log(arrayReduced)  // 18
No accumulator currentValue currentIndex return value
1 5 1 0 6
2 6 3 1 9
3 9 4 2 13
4 13 5 3 18

可以發現當我們的初始值是 5 的時候,accumulator 就是從 5 開始計算,後面接續 currentValue 的值累計。

實例 2

reduce() 也可以用來合併陣列。

const array = [[1, 3, 4, 5], [6, 7, 8], [9, 10, 11]]
const arrayReduced = array.reduce((accumulator, currentValue) => {
  return accumulator.concat(currentValue)
}, [])

console.log(arrayReduced) // [1, 3, 4, 5, 6, 7, 8, 9, 10, 11]

或者來計算相同字串的數量並以物件呈現。

const array = ['apple', 'orange', 'orange', 'apple', 'apple', 'banana']
const arrayReduced = array.reduce((accumulator, currentValue) => {
  if (currentValue in accumulator) {
    accumulator[currentValue]++
  } else {
    accumulator[currentValue] = 1
  }
  return accumulator
}, {})

console.log(arrayReduced) // {apple: 3, orange: 2, banana: 1}

reduceinitialValue 可以設為任一型態(數值、物件、陣列),而 accumulator 可繼承 initialValue 的型態並接收 currentValue 計算後的結果。

結論

  • 使用 reduce 可以進行比較細膩的比對與操作,尤其在陣列的 item 與 item 之間。
  • 執行前記得確認 initialValue,因為他會決定累加器的初始值,影響 return 的結果。