๐Ÿ‘จโ€๐Ÿ’ป Seungineer's GitHub Contribution

๐Ÿ› ๏ธ Tool/FE

[LeetCode-JS 30 days] #3.Function Transformations - 1(#ํ•จ์ˆ˜๊ฐ์ฒด)

seungineer = seungwoo + engineer 2024. 8. 9. 23:52

LeetCode JS 30 days Challenge

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์„ ์ตํž ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.

  1. Closures
  2. Basic Array Transformations
  3. Function Transformations
  4. Promises and Time
  5. JSON
  6. Classes

์ด 6๊ฐœ์˜ Part๋กœ ๊ตฌ์„ฑ๋˜๋ฉฐ ๋ณธ ํฌ์ŠคํŠธ์—์„œ๋Š” Function Transformations์— ๋Œ€ํ•ด ๋‹ค๋ฃฌ๋‹ค.

Function Composition

๊ฐ€์žฅ ๋งŽ์€ Upvote๋ฅผ ๋ฐ›์€ Discuss

์š”์•ฝ

ํ•ฉ์„ฑํ•จ์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ 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

๊ฐ€์žฅ ๋งŽ์€ Upvote๋ฅผ ๋ฐ›์€ Discuss

์š”์•ฝ

์™œ 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

๊ฐ€์žฅ ๋งŽ์€ Upvote๋ฅผ ๋ฐ›์€ Discuss

์š”์•ฝ

์ด์ „์— ํ˜ธ์ถœ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํŠธ๋ž˜ํ‚นํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•œ๋‹ค. ํŠธ๋ž˜ํ‚นํ•˜๊ธฐ ์œ„ํ•ด ํด๋กœ์ €๊ฐ€ ํฌํ•จ๋œ ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ํด๋กœ์ €์˜ ๊ฐ’์ด 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);
}
  •