2024.08.06 - [๐ ๏ธ Tool/FE] - [LeetCode-JS 30 days] #2. Array Transformation - 1(#์ํ)
[LeetCode-JS 30 days] #2. Array Transformation - 1(#์ํ)
2024.08.03 - [๐ ๏ธ Tool/FE] - [LeetCode-JS 30 days] #1. Closures ๊ฐ๋ - 1(#์๋ #๋ณด์กด) [LeetCode-JS 30 days] #1. Closures ๊ฐ๋ - 1(#์๋ #๋ณด์กด)์๊ธฐ ์ฝ๊ฒ ์ฐ์๊ณ ๋ง์ ์ฌ๋๋ค์๊ฒ ๊ฒ์ฆ๋ ์ค๋ช ์ด LeetCode Discuss์ ์ฌ๋ผ์ค
seungineer.tistory.com
์๊ธฐ ์ฝ๊ฒ ์ฐ์๊ณ ๋ง์ ์ฌ๋๋ค์๊ฒ ๊ฒ์ฆ๋ ์ค๋ช ์ด LeetCode Discuss์ ์ฌ๋ผ์ค๋ ๊ฒ์ ํ์ธํ๊ณ , JS Basic ๊ณต๋ถ์ ์ด๋ฅผ ํ์ฉํด๋ณด๊ณ ์ ํ์๋ค. LeetCode PS์ฒ๋ผ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ฉฐ JS์ basic skill์ ์ตํ ์ ์๋๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
- Closures
- Basic Array Transformations
- Function Transformations
- Promises and Time
- JSON
- Classes
์ด 6๊ฐ์ Part๋ก ๊ตฌ์ฑ๋๋ฉฐ ๋ณธ ํฌ์คํธ์์๋ Function Transformations์ ๋ํด ๋ค๋ฃฌ๋ค.
Function Composition
์์ฝ
ํฉ์ฑํจ์๋ฅผ ์ด๋ป๊ฒ JS๋ก ์ ์ฉํ ๊ฒ์ธ๊ฐ? Parameters๋ก ์ฃผ์ด์ง ํจ์ ๋ฐฐ์ด์ index๊ฐ ๊ฐ์ฅ ํฐ ํจ์๊ฐ ํฉ์ฑํจ์ ๊ฐ์ฅ ๋ด๋ถ์ ์ ์ฉ๋๋ ํจ์์ด๋ค. ์๋์ ์ ๊ทผ ๋ฐฉ์์ ์ด๋ค input data์ ์ฐ์์ ์ธ ๋ณํ์ ๊ฐํ๊ณ ์ ํ ๋ ์ ์ฉํ๋ค.
1. ReduceRight๋?
- JS์ array์์ ์ฌ์ฉ ๊ฐ๋ฅํ method๋ก reduce method์ ๋ฐฐ์ด ์ํ ๋ฐฉํฅ๋ง ๋ฐ๋์ด๋ค.
- reduceRight method๋ ๋ ๊ฐ์ arguments๊ฐ ์๋ callback function์ ๊ฐ๋๋ค. Arguments๋ 'accumulator' ์ 'current' value๋ฅผ ๋ํ๋ธ๋ค(a.k.a acc, cur).
- ์ด callback function์ array์ ๊ฐ element๋ก ํ ๋ฒ ์ฉ ํธ์ถ๋๋ค.
const arr = [1, 2, 3, 4, 5];
const sum = arr.reduceRight((prev, curr) => {
return prev + curr;
});
console.log(sum); // Output: 15
- ์ ์ฝ๋๋ arr ๋ฐฐ์ด์ element์ ์ดํฉ์ reverse order๋ก ๊ตฌํ๋ ๊ฒ์ด๋ค.
- reduce method์ ๋ง์ฐฌ๊ฐ์ง๋ก ์ด๊ธฐ๊ฐ์ด ์ง์ ๋์ด ์์ง ์์ ๊ฒฝ์ฐ ์ฒซ๋ฒ ์งธ ๋ฐฐ์ด element๊ฐ accumulator์ ํ ๋น๋๊ณ , ๋ ๋ฒ์งธ cur๋ถํฐ ๊ณ์ฐ๋๋ค.
- ๋ชจ๋ element๋ฅผ ์ํํ ํ์๋ accumulator๊ฐ ๋ฐํ๋๋ค
๋ฌธ์ ์ ์ ๋ต์ ์๋์ ๊ฐ๋ค.
var compose = function(functions) {
if (functions.length === 0) {
return function(x) { return x; };
}
return ((x) => {
return functions.reduceRight((acc, nextFn) => {
return nextFn(acc);
}, x);
})
};
const fn = compose([x => x + 1, x => 2 * x]);
console.log(fn(4)); // 9
- fn์๋ ์ผ๋ฐ์ ์ธ ํจ์๊ฐ ํ ๋น๋๋ค.
- return ((x) => { ... }) ์ผ๋ก ํจ์๊ฐ ๋ฐํ๋๊ธฐ ๋๋ฌธ
- fn(4)๋ฅผ ํ๋ฉด ๋ฐํ๋ ํจ์์ ์ธ์๋ก 4๊ฐ ์ ๋ ฅ๋จ
- x๋ก ์ธ์๊ฐ ์
๋ ฅ๋๋ฉด, ํฉ์ฑํจ์(composition function)๊ฐ ์คํ๋๋ค.
- functions.reduceRight()์ ์ํด์ ์ต์ข ์ ์ผ๋ก acc๊ฐ ๋ฐํ๋จ
Time, Space Complexity
- O(n), O(n)
reduceRight() method๋ฅผ ์ฌ์ฉํ๋ฉด Space Complexity๊ฐ O(n)์ด ๋๋ค.
reduceRight() method๊ฐ ์ฌ๊ท์ ํํ๋ก ์๋ํ๋ฉฐ, ๊ฐ ํจ์ ํธ์ถ์ด ๋๋ ๋๊น์ง ์คํ์ ํจ์ ํธ์ถ์ด ์์ด๊ธฐ ๋๋ฌธ์ด๋ค. ๋ชจ๋ ํจ์๊ฐ ์คํ๋ ํ์์ผ ์ต์ข ์ ์ผ๋ก ์คํ์์ ํจ์๋ค์ด ์ ๊ฑฐ๋๋ค. ๊ฐ ํจ์ ํธ์ถ ์ ํจ์์ ์คํ ์ปจํ ์คํธ๊ฐ ์ฝ ์คํ์ ์ถ๊ฐ๋๊ณ , ๊ฐ ํจ์๊ฐ ๋ฐํ๋๊ธฐ ์ ์ ๋ค์ ํจ์๊ฐ ์คํ์ ์์ด๋ ๊ตฌ์กฐ๋ก, ์ฝ ์คํ์ ์ต๋ n๊ฐ์ ํจ์๊ฐ ๋์์ ์กด์ฌํ ์ ์๊ฒ ๋๋ ๊ฒ์ด๋ค.
Space Complexity == O(1)์ธ ์ ๊ทผ ๋ฐฉ์
var compose = function(functions) {
if (functions.length === 0) {
return function(x) { return x; };
}
return function(x) {
let result = x;
for (let i = functions.length - 1; i >= 0; i--) {
result = functions[i](result);
}
return result;
}
};
- reduceRight() method์ ๋ฌ๋ฆฌ ๋ฐ๋ณต๋ฌธ์ ์ฌ์ฉํ์ฌ ํจ์๋ฅผ ์์ฐจ์ ์ผ๋ก ์คํํ๋ค.
- ๊ฐ ํจ์ ์คํ ๊ฒฐ๊ณผ๋ฅผ result ๋ณ์์ ์ ์ฅํ๋ค.
- result ๋ณ์๋ ๋ฎ์ด์จ์ง๋ ๊ฒ์ผ๋ก ์ฝ ์คํ์ ํจ์๊ฐ ์์ด์ง ์์
- ์ด๋ค ํจ์๊ฐ ์คํ๋๋ ํจ์๊ฐ ๋๋๋ฉด ์ฝ ์คํ์์ ์ ๊ฑฐ๋จ
- ์ด ๊ณผ์ ์์ ๋จ ํ๋์ result ๋ณ์๋ง ์ฌ์ฉ๋๋ฉฐ, ์ถ๊ฐ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ด ๋ฐ์ํ์ง ์๋๋ค.
Return Length of Arguments Passed
์์ฝ
์ rest parameter๋ฅผ ์ฌ์ฉํ๋๊ฐ?
Javascript์์ rest parameter๋ฅผ ์ฌ์ฉํด ํจ์ ๋ด์์ ๋ฌดํํ ์์ ์ธ์๋ฅผ ๋ฐฐ์ด๋ก ํํํ ์ ์๋ค. ์ด๋ฅผ ํตํด ๋ช ์์ ์ผ๋ก ์ ์ํ์ง ์๊ณ ๋ ์ฌ๋ฌ arguments๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค.
let array = [1,2,3,4,5];
// ์ผ๋ฐ์ ์ธ arguments๊ฐ ์ ๋ฌ๋๋ ๋ฐฉ์
function sum (a,b,c,d,e){
console.log(a,b,c,d,e) // 1 2 3 4 5
}
// ๋ธ๋ฃจํธ ํฌ์ค method
sum(array[0],array[1],array[2],array[3],array[4]);
// ๋ฌธ์ : ๊ฐ๊ฐ์ value๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก passํด์ผ ํ๋ค.
// ์ ๋ฐฉ์์ arguments๊ฐ ๋ง์์ก์ ๋ ํ๋ ํ๋ pass ํด์ผ ํ๋ค๋ ์ ์์ ํ๋นํ์ง ์๋ค.
// spread parameter๋ฅผ ์ฌ์ฉํ๋ฉด ๋ชจ๋ value๋ฅผ ํ ๋ฒ์ passํ ์ ์๋ค.
sum(...array);
// ํจ์ ๋ด์์ spread parameter๋ ๋ฐฐ์ด(array)๋ก์ ๋ฌดํํ ์์ arguments๋ฅผ ์ ๋ฌํ๋๋ก ํ๋ค.
function sum (...args){
console.log(args) // [1,2,3,4,5]
}
// arguments์ ์ผ๋ถ๋ฅผ array๋ก ๊ฐ์ ธ์ค๊ธฐ ์ํด rest parameter๋ฅผ ์ฌ์ฉํ ์๋ ์๋ค.
function sum (a,b,...args){
console.log(a,b,args) // 1 2 [3,4,5]
}
rest parameter VS spread parameter
- values๋ฅผ ์ด๋๊ฐ์ passํ๋ ๊ฒฝ์ฐ๋ spread parameter
- ํ ๋น ์ฐ์ฐ์์ ์ฐ์ธก
- function์ผ๋ก arguments๋ฅผ pass๋๋ ๊ฒฝ์ฐ
- values๋ฅผ receiveํ๋ ๊ฒฝ์ฐ rest parameter
- ํ ๋น ์ฐ์ฐ์์ ์ข์ธก
- function์์ receivedํ parameter
// Spread parameters
const arr = [1, 2, 3];
myFunction(...arr);
// Rest parameters
const myFunction = function(...arr){
// do something
}
Allow One Function Call
์ด์ ์ ํธ์ถ๋์๋์ง ์ฌ๋ถ๋ฅผ ํธ๋ํนํ ์ ์๋ ํจ์๋ฅผ ๋ฐํํด์ผ ํ๋ค. ํธ๋ํนํ๊ธฐ ์ํด ํด๋ก์ ๊ฐ ํฌํจ๋ ํจ์๋ฅผ ๋ฐํํ ์ ์๋ค. ํด๋ก์ ์ ๊ฐ์ด default false์๋ค๊ฐ ํ ๋ฒ ํธ์ถ๋์ด true๋ก ๋ฐ๋๋ฉด ๋ค์ ํจ์ ํธ์ถ๋ถํฐ๋ ์ง์ undefined๋ฅผ ๋ฐํํ๋ ํจ์๋ฅผ ์์ฑํ๋ค.
๋ฐํ๋ ์ด๋ค ํจ์์ ์ํ๋ฅผ ์ ์ฅํ๊ธฐ ์ํด ํด๋ก์ ๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
๋ฐํ๋ ํจ์๋ ํด๋ก์ ๊ฐ ์์ฑ๋ ๋์ context๋ฅผ ๊ณ์ํด์ ์ ์งํ๊ธฐ ๋๋ฌธ!
var once = function(fn) {
let hasBeenCalled = false;
let result;
return function(...args) {
if (!hasBeenCalled) {
result = fn(...args);
hasBeenCalled = true;
return result;
} else {
return undefined;
}
}
};
let fn = (a,b,c) => (a + b + c);
let onceFn = once(fn);
console.log(onceFn(1,2,3)); // 6
console.log(onceFn(2,3,6)); // undefined
- hasBeencalled ํด๋ก์ ๋ณ์๋ฅผ ํตํด ํจ์์ ์ฌํธ์ถ์ ๋ง๊ณ ์์
Class๋ฅผ ์ด์ฉํ ์ ๊ทผ ๋ฐฉ๋ฒ
์ ์ฝ๋์ ๋ฐํ๋ ํจ์์ ์ญํ ์ ํ ์ ์๋ Once Class๋ฅผ ์ ์ํ์ฌ ํจ์์ ์ฌํธ์ถ์ ๋ง์ ์๋ ์๋ค.
class Once {
hasBeenCalled = false;
result;
call(fn, ...args) {
if (!this.hasBeenCalled) {
this.result = fn(...args);
this.hasBeenCalled = true;
return this.result;
} else {
return undefined;
}
}
}
function once(fn) {
const instance = new Once();
return instance.call.bind(instance, fn);
}