如果你沒看過 FizzBuzz,題目是這樣的:
給定一串從 1 到 n 的數字:
a. 如果是 3 的倍數,就印出 “Fizz”
b. 如果是 5 的倍數,就印出 “Buzz”
c. 如果同時是 3 和 5 的倍數,就印出 “FizzBuzz”
d. 將印出的結果回傳為一個矩陣。
一般來說,最直覺的想法就是用 for 迴圈,然後裡面用很多 if 判斷式
const fizzBuzz = (n) => {
const result = [];
for ( let i = 0; i < n; i++ ) {
if(n % 15 === 0) {
result[n] = 'FizzBuzz';
} else if(n % 3 === 0) {
result[n] = 'Fizz';
} else if(n % 5 === 0) {
result[n] = 'Buzz';
} else {
result[n] = '' + n; // output should be String
}
}
return result;
};
但是這樣太過 imperative,只是把解決步驟描述一遍,非常機械化,之後若回頭來看程式碼的時候,需要花比較多時間才能看懂。
如果要再進階一點,for 迴圈與 if 判斷處可以修改一下,變成
const fizzBuzz = (n) => {
const condition = n =>
( n % 15 === 0 ) ? 'FizzBuzz' :
( n % 3 === 0 ) ? 'Fizz' :
( n % 5 === 0 ) ? 'Buzz' : '' + n;
const result = [];
Array.from(Array(n)).forEach((v, i) => {
result[i] = condition(i + 1);
});
return result;
};
這是比較declarative 的寫法,著重在描述想要達成的目的,而非流程與步驟
所以可以看到,我除了用forEach
代替for
之外(盡量善用內建函式,也更不容易出錯),我還把條件判斷包成一個 function,好處是,在閱讀時可以讓我們對於整個fizzBuzz()
的理解「分塊」進行,不需要讀完整段就能知道這段程式的「目的」。
再然後,我看到有人這樣寫
const fizzBuzz = (n) => new Array(n).fill(0).map((a, i) =>
(++i % 3 ? '' : 'Fizz') + (i % 5 ? '' : 'Buzz') || '' + i);
簡潔有力,我跪!