본문 바로가기
IT/JavaScript

자바스크립트 고차함수 문제풀이

by 삐약 개발자 2024. 12. 18.
반응형

take

take 는 배열의 처음 n 개의 element를 담은 새로운 배열 리턴


_.take = function (arr, n) {
    if (n === undefined || n < 0){
        return [];
    }
    return _.slice(arr, 0, n);
};

drop

drop 은 take와는 반대로, 처음 n개의 element를 제외한 새로운 배열을 리턴


_.drop = function (arr, n) {
  if (n === undefined || n < 0) {
    return _.slice(arr, 0, n);
  }else if(n >= arr.length){
    return [];
  }
  return _.slice(arr, n, arr.length);
};

last

last 는 배열의 마지막 n개의 element를 담은 새로운 배열을 리턴


_.last = function (arr, n) {
  if (n === undefined || n < 0) {
    return _.slice(arr, arr.length - 1);
  } else if (n >= arr.length) {
    return _.slice(arr, 0);
  }
  return _.slice(arr, arr.length - n);
};

_이렇게도 가능


_.last = function (arr, n) {
  if (n === undefined || n < 0) {
    return _.slice(arr, arr.length - 1);
  }

  if(n === 0) return [];

  return _.slice(arr, -n);
  };

each

each 는 collection의 각 데이터에 반복적인 작업을 수행

파라미터에 (ele, idx, arr) 이 있을때
콜백 함수로 ele 만 사용가능 단 idx 만 사용은 안됨 순서는 지정이 되있기에
idx 사용하고 싶다면 ele, idx 사용해야 함!


_.each = function (collection, iteratee) {
  if(Array.isArray(collection)){
    for(let i = 0; i < collection.length; i++){
      iteratee(collection[i], i, collection);
    }
  }else if(typeof collection == 'object'){
    for(let key in collection){
      iteratee(collection[key], key, collection);
    }
  };
};
  • 배열 먼저 거르고 객체 타입 확인

filter

filter는 test 함수를 통과하는 모든 요소를 담은 새로운 배열을 리턴


_.filter = function (arr, test) {
  let result = [];

  _.each(arr, function(ele){
    if(test(ele)){
      result.push(ele);
    }
  });

  return result;
};

reject

reject는 filter와 정반대로 test 함수를 통과하지 않는 모든 요소를 담은 새로운 배열을 리턴


_.reject = function (arr, test) {
  let result = [];

  _.each(arr, function(ele){
    if(!test(ele)){
      result.push(ele);
    }
  });

  return result;
};

_위에 만들어 놓은 filter 메서드 사용해서 간단하게 작성 가능


_.reject = function (arr, test) {
  return _.filter(arr, function(el){
      return !test(el);
  });
};

uniq

uniq 는 주어진 배열의 요소가 중복되지 않도록 새로운 배열을 리턴


_.uniq = function (arr) {
  let result = [];

  _.each(arr, function(ele){
    let isTrue = true;
    for(let i = 0; i < result.length; i++){
      if(result[i] === ele){
        isTrue = false;
        break;
      }
    }
    //위에 for 문 each 로 바꿀수 있음
    %% _.each(result, function(resultEl){
      if(resultEl === ele){
        isTrue = true;
      }
    }); %%

    if(isTrue){
      result.push(ele);
    }
  });

  return result;
};

_filter 사용 가능


_.uniq = function (arr) {
  let result = [];

  _.filter(arr, function(el){
    if(_.indexOf(result, el) === -1){
      result.push(el);
      return true;
    }else{
      return false;
    }
  });

  return result;
};

map

map 은 iteratee(반복되는 작업)를 배열의 각 요소에 적용(apply)한 결과를 담은 새로운 배열을 리턴


_.map = function (arr, iteratee) {
  let result = [];

  _.each(arr, function(el, idx, collection){
    let currentMappedEl = iteratee(el, idx, collection);
    result.push(currentMappedEl);
  });


  _.each(arr, function(ele){
    let isTrue = true;
    _.each(result, function(resultEl){
      if(resultEl === ele){
        isTrue = true;
      }
    });

    if(isTrue){
      result.push(iteratee(ele));
    }
  });

  return result;
};

_더 간단하게 사용 가능


_.map = function (arr, iteratee) {
  let result = [];

  _.each(arr, function(el, idx, collection){
    let currentMappedEl = iteratee(el, idx, collection);
    result.push(currentMappedEl);
  });

  return result;
};

pluck

take


_.pluck = function (arr, keyOrIdx) {
  let result = [];

  _.map(arr, function (item) {
    result.push(item[keyOrIdx]);
  });

  return result;
};

_할당하지 않고 사용 가능


_.pluck = function (arr, keyOrIdx) {
    return _.map(arr, function (item){
        return item[keyOrIdx]
    })
};

reduce

take



once

once 는 callback 함수를 한 번만 호출하는 '함수'를 리턴


_.once = function (func) {
  let isTrue = false;
  let result;

  return function (...oper) {
    if(!isTrue){
        // result = func(...oper);
        //위에를 아래처럼 사용가능
        result = func.apply(this, args);
        isTrue = true;
    }
    return result;
  };
};

delay


_.delay = function (func, wait, ...oper) {
    setTimeout(()=>{
        func(...oper);
    }, wait);
};

includes

배열이 주어진 값을 포함하는지 확인


_includes = function (arr, target) {
    let isTrue = false;
    _.each(arr, (el) => {
        if(el === target) isTrue = true;
    });
    return result;
};

every

배열의 모든 요소가 test 함수(iteratee)를 통과하면 true를, 그렇지 않은 경우 false를 리턴


_.every = function(arr, iteratee){
    if(!iteratee) iteratee = x => x;
    if(arr.length < 1) return true;

    for(let i = 0; i < arr.length; i++){
        if(!iteratee(arr[i])) return false;
    };

    return true;
};

some

배열의 요소 중 하나라도 test 함수(iteratee)를 통과하면 true를, 그렇지 않은 경우 false를 리턴


_.some = function (arr, iteratee) {
  let result = 0;

  if(!iteratee) {
    iteratee = x => x;
  }else if(arr.length < 1){
    return false;
  }

  for(let i = 0; i < arr.length; i++){
    if(iteratee(arr[i])){
      result++;
    }
  }

  return result > 0 ? true : false;
};

_.some = function (arr, iteratee) {
  if(!iteratee) iteratee = x => x;
  if(arr.length < 1) return false;

  for(let i = 0; i < arr.length; i++){
    if(iteratee(arr[i])) return true;
  };

  return false;
};

extend

여러 개의 객체를 입력받아, 순서대로 객체를 결합

  • 첫 번째 입력인 객체를 기준으로 다음 순서의 객체들의 속성을 덮어씀

_.extend = function (...objs) {
  let result = objs[0];

  _.each(_.slice(objs,1), function(obj){
    _.each(obj, function(value, key){
      result[key] = value;
    });
  });

  return result;
};

defaults

extend와 비슷하게 동작하지만, 이미 존재하는 속성(key)을 덮어쓰지 않음


_.defaults = function (...objs) {

  let result = objs[0];

  _.each(_.slice(objs,1), function(obj){
    _.each(obj, function(value, key){
      if(result[key] === undefined){
        result[key] = value;
      }
    });
  });

  return result;
};

==zip==

여러 개의 배열을 입력받아, 같은 index의 요소들을 묶어 배열로 만듬


_.zip = function (...arr) {
  let result = [];

  const maxLength = Math.max(..._.map(arr, (el) => el.length));
  // 위와 아래가 같은 코드임 단 let 은 값이 변할수 있기에 const 로 교체하는게 좋음 또한 아래는 each 로 최댓값을 구함 그거 대신 Math.max 메서드 사용해서 함축 가능!!!
  // let length = 0;
  // _.each(arr, function(ele){
  //   if(ele.length > length) length = ele.length
  // });

  for(let i = 0; i < maxLength; i++){
    let temp = [];
    _.each(arr, function(ele){
      temp.push(ele[i])
    });
    result.push(temp);
  }

  return result;
};

zipStrict


_.zipStrict = function (...arr) {
    let result = [];
    const minLength = Math.min(..._.map(arr, el => el.length));

    for(let i = 0; i < minLength; i++){
        let temp = [];
        _.each(arr, el => {
            temp.push(el[i]);
        })
        result.push(temp);
    }
    return result;
}

intersection


_.intersection = function (...arr) {
  let result = [];

  _.each(arr[0], function(el){
     let isTrue = true;

     _.each(_.slice(arr,1), function(ar){
       if(!_.includes(ar, el)){
         isTrue = false;
       };
     });

     if(isTrue){
       result.push(el);
     };
   });

   return result;
};

_filter, every, includes 사용해서 활용가능


_.intersection = function (...arr) {
  return _.filter(arr[0], ele => {
    return _.every(_.slice(arr,1), restEle => {
      return _.includes(restEle, ele)
    })
  })
};

difference


_.difference = function (...arr) {
  let result = [];

  _.each(arr[0], el => {
    let isTrue = true;

    _.each(_.slice(arr,1), ar => _.includes(ar, el) ? isTrue = false : null);

    if(isTrue) result.push(el);
  })

  return result;
};

_다른 방법


_.difference = function (firstArr,...arr) {
  let result = [];

  // 나머지 요소를 병합
  _.each(arr, function(innerArray) {
    _.each(innerArray, function(el) {
      result.push(el);
    });
  });

  return _.filter(firstArr, function(el) {
    return !_.includes(result, el);
  });
};

sortBy

memoize

throttle

반응형