[Array][Easy] Filter
🔸 題目描述
給定一個整數陣列 arr
和一個過濾函式 fn
,回傳一個過濾後的陣列 filteredArr
。
函式 fn
接受一個或兩個參數:
arr[i]
是來自arr
的數字i
是arr[i]
的索引
filteredArr
應該只包含來自 arr
的元素,其中表達式 fn(arr[i], i)
評估為真值。真值是指 Boolean(value)
返回 true
的值。此題不得使用 JavaScript 內建的 Array.filter
方法來解。
// 範例一
輸入: arr = [0,10,20,30], fn = function greaterThan10(n) { return n > 10; }
輸出: [20, 30]
解說:
const newArray = filter(arr, fn); // [20, 30]
該函式把沒有大於 10 的數字過濾掉
// 範例二
輸入: arr = [1, 2, 3], fn = function firstIndex(n, i) { return i === 0; }
輸出: [1]
解說:
fn 也可以接受每個元素的索引,在這個案例中,該函式把索引不等於 1 的數字過濾掉
💭 分析與思路
問題釐清
- 傳入的陣列的值是否限制為只有 number
- 其他相對明確,就是作出一個類似 array.filter 的方法即可
提出測試案例
- 能通過基本測資
- 能確認 fn 傳不傳第二個參數的正確性
- 能列出一些 edge case,如空陣列、fn 結果都不符合等狀況
提出思路
- 用 for 迴圈對 arr 迭代,並執行 fn 確認是否為 truthy,是的話則放入準備回傳的結果陣列
實作
雖然一開始限制只用 number,但發現其實也是改成泛型可以支援各種型別:
const filter = <T>(arr: T[], fn: (n: T, i: number) => boolean) => {
const res: T[] = [];
// 用 for 迴圈對 arr 迭代,並執行 fn 確認是否為 truthy,是的話則放入準備回傳的結果陣列
for (let i = 0; i < arr.length; i++) {
if (fn(arr[i], i)) {
res.push(arr[i]);
}
}
return res;
};
export default filter;
或是想用 reduce 縮寫也可:
const filterWithReduce = <T>(arr: T[], fn: (n: T, i: number) => boolean) => {
return arr.reduce<T[]>((accu, curr, index) => {
if (fn(curr, index)) {
accu.push(curr);
}
return accu;
}, []);
};