Javascript 的陣列方法
Array Methods(陣列方法)
傳統陣列操作方法
在 ES6 以前就有出現 push、pop、shift、unshift 這四種用於操作陣列的方法,許多 LeetCode 題目會禁止使用 ES6 以後的功能,用於考察對於基本 JavaScript 語法的熟悉程度,此時就是展現對這些陣列方法的熟悉度了。
以下是傳統陣列操作方法的介紹:
.push(element1, element2, ..., elementN)
:將一個或多個元素添加到陣列的末尾。
const array = [1, 2, 3];
array.push(4, 5);
console.log(array); // [1, 2, 3, 4, 5]
.pop()
:刪除並返回陣列的最後一個元素。
const array = [1, 2, 3];
const removedElement = array.pop();
console.log(removedElement); // 3
console.log(array); // [1, 2]
.shift()
:刪除並返回陣列的第一個元素。
const array = [1, 2, 3];
const removedElement = array.shift();
console.log(removedElement); // 1
console.log(array); // [2, 3]
.unshift(element1, element2, ..., elementN)
:將一個或多個元素添加到陣列的開頭。
const array = [2, 3];
array.unshift(0, 1);
console.log(array); // [0, 1, 2, 3]
Array Methods 的小練習
前面有提過 push 的方法能將元素添加到陣列的末尾,這邊透過 push 熟悉一下 Array Methods。
以下會用兩個例子來講解:
- 利用 push 讓 resultArray 這個空陣列的值與 Array 相同
- LeetCode: Apply Transform Over Each Element in Array
1. 利用 push 讓 resultArray 這個空陣列的值與 Array 相同
第一個例子是如果 resultArray 是空陣列,希望把 Array push 給 resultArray:
const Array = [1,2,3];
let resultArray = [];
resultArray.push(Array);
console.log(resultArray); // [[1, 2, 3 ]]
注意!此時 console 出的會是 [[1, 2, 3 ]]
而非預期 [1, 2, 3]
,這是因為它實際上將整個 Array
陣列作為一個元素推送到 resultArray
中。
比較直覺的做法可以使用 for 來一個一個將元素 push 進 resultArray
,也可以直接使用 spread operator (運算展開符) ...
。
const Array = [1,2,3];
let resultArray = [];
for (let i = 0; i < Array.length; i++) {
resultArray.push(Array[i])
}
// 或是直接使用 let resultArray = [...Array];
console.log(resultArray); // [1, 2, 3 ]
2. LeetCode: Apply Transform Over Each Element in Array
第二個例子是 LeetCode 的 Easy 題,題目如下:
Given an integer array arr
and a mapping function fn
, return a new array with a transformation applied to each element.
The returned array should be created such that returnedArray[i] = fn(arr[i], i)
.
Please solve it without the built-in Array.map
method.
Example 1:
// Input:
arr = [1,2,3]
fn = function plusone(n) { return n + 1; }
// Output:
// [2,3,4]
Explanation:
const newArray = map(arr, plusone); // [2,3,4]
The function increases each value in the array by one.
Example 2:
// Input:
arr = [1,2,3]
fn = function plusI(n, i) { return n + i; }
// Output:
// [1,3,5]
Explanation: The function increases each value by the index it resides in.
Example 3:
// Input:
arr = [10,20,30]
fn = function constant() { return 42; }
// Output:
// [42,42,42]
Explanation: The function always returns 42.
解題
像這一題就有禁止使用 ES6 的 map 方法,所以我們可以設計一個 map() 函式,這個函式能輸入 arr 與 fn,接著透過前一例子中的 for 迴圈方式來將 arr 透過 fn 來做陣列元素的轉換,架構如下:
const map = (arr, fn) => {
let transformedArray = [];
for (i = 0; i < arr.length; i++) {
transformedArray.push(fn(arr[i]))
}
return transformedArray
}
arr = [1,2,3]
// Design fn
console.log(map(arr, fn));
接著根據題目敘述設計 fn plusone()
、plusI()
、constant()
:
const map = (arr, fn) => {
let transformedArray = [];
for (let i = 0; i < arr.length; i++) {
transformedArray.push(fn(arr[i], i));
}
return transformedArray;
};
const arr = [1, 2, 3];
const plusone = (n) => n + 1;
const plusI = (n, i) => n + i; // 設計讓陣列元素 + 該陣列元素的 index
const constant = () => 42; // 陣列元素會變一個 constant 的值
console.log(map(arr, plusone));
console.log(map(arr, plusI));
console.log(map(arr, constant));
- 在
plusone
中,fn(arr[i], i)
會將arr[i]
作為n
傳遞給 ,而i
會被忽略。 - 在
plusI
中,fn(arr[i], i)
會將arr[i]
作為n
,i
作為i
傳遞給plusI
,這樣就成功加入 index 值。 - 在
constant
中不接受任何參數,每次都返回 42。
ES6 增加的 Array Methods
ES6 的陣列方法,包括 map、filter 和 reduce。
.map(callback)
:創建一個新陣列,該陣列的元素是將原陣列的每個元素按照指定的函數進行轉換後的值。
// Example 1: 陣列中的每個元素都加 1
const array = [1, 2, 3];
const plusoneArray = array.map((x) => x + 1);
console.log(plusoneArray); // [2, 3, 4]
// Example 2: 陣列中的每個元素都做平方
const squaredArray = array.map(x => x ** 2);
console.log(squaredArray); // [1, 4, 9]
.filter(callback)
:創建一個新陣列,其中包含通過指定函數測試的所有元素。
// Example 1: 過濾出大於 2 的元素
const array = [1, 2, 3, 4, 5];
const filteredArray = array.filter((x) => x > 2);
console.log(filteredArray); // [3, 4, 5]
// Example 2: 過濾出偶數(除以 2 會為 0)
const evenNumbers = array.filter(x => x % 2 === 0);
console.log(evenNumbers); // [2, 4]
.reduce(callback, initialValue)
:將陣列的所有元素累積到一個單一的值中,通過指定的函數進行累加。
// Example 1: 累加數字
const array = [1, 2, 3];
const sum = array.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 6
// Example 2: 累加字串
const words = ['Hello', ' ', 'world', '!'];
const sentence = words.reduce((acc, curr) => acc + curr, '');
console.log(sentence); // "Hello world!"
使用傳統陣列方法來實作 ES6 的 filter 與 reduce
以下兩個 Easy 的 LeetCode 題都禁止使用 ES6 的陣列方法,會需要使用傳統陣列方法來解決。
LeetCode: 2634. Filter Elements from Array
Given an integer array arr
and a filtering function fn
, return a filtered array filteredArr
.
The fn
function takes one or two arguments:
arr[i]
- number from thearr
i
- index ofarr[i]
filteredArr
should only contain the elements from thearr
for which the expressionfn(arr[i], i)
evaluates to a truthy value. A truthy value is a value whereBoolean(value)
returnstrue
.
Please solve it without the built-in Array.filter
method.
Example 1:
// Input:
arr = [0,10,20,30]
fn = function greaterThan10(n) { return n > 10; }
// Output:
// [20,30]
Explanation:
const newArray = filter(arr, fn); // [20, 30]
The function filters out values that are not greater than 10
Example 2:
// Input:
arr = [1,2,3]
fn = function firstIndex(n, i) { return i === 0; }
// Output:
// [1]
Explanation: fn can also accept the index of each element In this case, the function removes elements not at index 0
Example 3:
// Input:
arr = [-2,-1,0,1,2]
fn = function plusOne(n) { return n + 1 }
// Output:
// [-2,0,1,2]
Explanation: Falsey values such as 0 should be filtered out
解題
const filter = (arr, fn) => {
let filteredArr = [];
for (let i = 0; i < arr.length; i++) {
let result = fn(arr[i], i);
if (result) {
filteredArr.push(arr[i]);
}
}
return filteredArr;
};
// Example 1
const arr1 = [0, 10, 20, 30];
const greaterThan10 = (n) => n > 10;
console.log(filter(arr1, greaterThan10)); // [20, 30]
// Example 2
const arr2 = [1, 2, 3];
const firstIndex = (n, i) => i === 0;
console.log(filter(arr2, firstIndex)); // [1]
// Example 3
const arr3 = [-2, -1, 0, 1, 2];
const plusOne = (n) => n + 1;
console.log(filter(arr3, plusOne)); // [-2, 0, 1, 2]
2626. Array Reduce Transformation
Given an integer array nums
, a reducer function fn
, and an initial value init
, return the final result obtained by executing the fn
function on each element of the array, sequentially, passing in the return value from the calculation on the preceding element.
This result is achieved through the following operations: val = fn(init, nums[0]), val = fn(val, nums[1]), val = fn(val, nums[2]), ...
until every element in the array has been processed. The ultimate value of val
is then returned.
If the length of the array is 0, the function should return init
.
Please solve it without using the built-in Array.reduce
method.
Example 1:
// Input:
nums = [1,2,3,4]
fn = function sum(accum, curr) { return accum + curr; }
init = 0
// Output:
// 10
Explanation: initially, the value is init=0. (0) + nums[0] = 1 (1) + nums[1] = 3 (3) + nums[2] = 6 (6) + nums[3] = 10 The final answer is 10.
Example 2:
// Input:
nums = [1,2,3,4]
fn = function sum(accum, curr) { return accum + curr * curr; }
init = 100
// Output:
// 130
Explanation: initially, the value is init=100. (100) + nums[0] nums[0] = 101 (101) + nums[1] nums[1] = 105 (105) + nums[2] nums[2] = 114 (114) + nums[3] nums[3] = 130 The final answer is 130.
Example 3:
// Input:
nums = []
fn = function sum(accum, curr) { return 0; }
init = 25
// Output:
// 25
Explanation: For empty arrays, the answer is always init.
解題
const reduce = (nums, fn, init) => {
let reducedValue = init;
for (let i = 0; i < nums.length; i++) {
reducedValue = fn(reducedValue, nums[i]);
}
return reducedValue;
};
const nums = [1, 2, 3, 4];
const sum = (accum, curr) => accum + curr;
const init = 0;
const nums2 = [1,2,3,4]
const sum2 = (accum, curr) => accum + curr * curr;
const init2 = 100;
const nums3 = []
const sum3 = (accum, curr) => 0;
const init3 = 25;
console.log(reduce(nums, sum, init));
console.log(reduce(nums2, sum2, init2));
console.log(reduce(nums3, sum3, init3));