更高階的函式可以讓我們更專注在我們想要開發的功能上面。
就在昨天的範例中,我們第一次使用了 reduce
這個函式,相信應該會有許多小夥伴驚訝了一下。不過,有寫過函數式程式語言(Functional Programming, FP)的小夥伴一定對這非常的熟悉。因為 reduce
是函數式程式語言裡非常普通而且常見的高階函數。除了 reduce
(在FP中我們叫它 fold
) 之外,還有 map
, filter
...等。而這些高階函數主要的目的是針對操作一個集合(Array, list ...等)並將 for loop 和 if else 給抽象化,也就是說當你對一個集合做操作時,你不再需要告訴它該怎麼做,只要告訴他你想做什麼。
就以今天要介紹的 reduce
開始吧!
reduce
(又稱為 fold
)主要的目的就是將一個集合進行操作最後的結果就是一個值。
舉個例子來說,我有一個 Array, 其內容為 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 我想要做的是得到所有奇數的總和,如果我不使用這個 reduce
高階函數,我可能要這樣做:
// 我們的測試資料
let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function sumOddNumber(...numbers: number[]): number {
let result = 0;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 == 1) {
result = result + numbers[i];
}
}
return result;
}
console.log("所有奇數總和:" + sumOddNumber(data)); // answer is 25
如果我使用 reduce
這個高階函數,我就不用告訴他怎麼做,我只要告訴他我要做什麼。
Array.reduce(callback_function, initial_value);
其中:
callback_function
為輸入兩個參數,輸出一個值。而兩個參數中,第一個是最後的結果,第二個是陣列裡的每一個值,假設有十個元素,則這個 callback_function 就會被呼叫十次,每次都帶進一個新的元素進去。initial_value
為 callback_function
結果 的初始值
所以第一個範例我們改用 reduce
就可以這樣寫:
// 我要做的事情是將奇數加總
let sumOdd = (sum: number, num: number): number => {
if (num % 2 == 1)
return sum + num;
return sum;
}
// 使用 reduce function
function sumOddNumber2(numbers: number[]): number {
return numbers.reduce(sumOdd, 0);
}
// 呼叫 sumOddNumber2, answer is 25
console.log("所有奇數總和(使用reduce):" + sumOddNumber2(data));
上面的範例我們還可以把 sumOddNumber2 改寫成如下方式(sumOddNumber3):
let sumOddNumber3 = (numbers: number[]) => numbers.reduce(sumOdd, 0);
console.log("所有奇數總和(使用reduce+箭頭函數):" + sumOddNumber3(data));
這樣一來我們就不用去使用 for loop 去跑片所有的元素,我們只要專注在我們要做的事情,也就是把所有的奇數相加就好。
如果我們有一個陣列 subject
如下,我想要透過一個函式把 subject
轉換成註解中的結果,並且要使用 reduce
該怎麼做呢?
// 欲操作的資料
let subject: string[] = ["Math", "English", "Data Structure", "C++", "Algorithm"];
// 想要得到的答案是:"Math, English, Data Structure, C++, Algorithm"