프로젝트/미니 프로젝트 & 과제

[과제] 반복문으로 map, filter, reduce 만들기

JeanneLee57 2023. 3. 17. 21:49

 

고차함수를 배웠으니 자바스크립트의 기본 내장 고차함수들을 반복문을 이용해 직접 구현해 보자.

자바스크립트의 underscore라는 라이브러리는 배열과 객체를 처리하는 데 유용한 함수들을 제공하는데,

이와 비슷한 기능을 직접 만들어 보는 것이 오늘의 과제였다.

 

먼저 map, filter, reduce를 만들기 전에 forEach에 해당하는 함수부터 만들어준다.

배열인지 배열이 아닌 객체인지 여부를 확인해 각각의 요소마다 콜백함수를 적용한다.

_.each = function (collection, iteratee) {
  if (Array.isArray(collection)) {
    for (let i = 0; i < collection.length; i++) {
      iteratee(collection[i], i, collection);
    }
  } else
    for (let x in collection) {
      iteratee(collection[x], x, collection);
    }
};

 

._filter 함수는 test 함수의 결과가 true인 요소만을 담은 새로운 배열을 리턴한다.

_.filter = function (arr, test) {
  let newArr = [];
  _.each(arr, (x) => {
    if (test(x)) newArr.push(x);
  });
  return newArr;
};

 

_.map 함수 는각 요소에 콜백함수를 적용한 결과를 리턴한다.

_.each는 명시적인 리턴값이 없는데 비해 _.map은 결과를 리턴해 준다는 것이다.

_.map = function (arr, iteratee) {
  let newArr = [];
  _.each(arr, (x) => {
    newArr.push(iteratee(x));
  });
  return newArr;
};

 

_.reduce는 초기값이 설정돼 있으면 초기값부터 시작해 각 요소에 콜백함수를 적용한 뒤 누산기에 새로운 값을 할당해 준다.

초기값이 없으면 배열의 첫 요소를 누산기로 시작한다.

_.reduce = function (arr, iteratee, initVal) {
  if (initVal !== undefined) {
    let acc = initVal;
    _.each(arr, function (cur, idx, collection) {
      acc = iteratee(acc, cur, idx, collection);
    });
    return acc;
  }
  let acc = arr[0];
  _.each(_.drop(arr, 1), function (cur, idx, collection) {
    acc = iteratee(acc, cur, idx, collection);
  });
  return acc;
};

 

보너스로 구현하는 데 꽤 머리를 굴려야 했던 _.sortBy 함수.

각 요소에 콜백함수를 적용한 결과를 기준으로 요소를 비교해 정렬한다.

_.sortBy = function (arr, transform, order) {
  let newArr = [...arr];
  if (transform === undefined) return arr.sort();
  function compare(a, b) {
    if (transform(a) === transform(b)) return 0;
    return transform(a) > transform(b) ? order || 1 : order * -1 || -1;
  }
  return newArr.sort(compare);
};