접기 - group_by, count_by

devjune·2021년 10월 4일
0

ES5

목록 보기
13/14

group_by는 특정 조건을 만족시키는 값들을 그룹지어 리턴하는 기능을 가진다. 예를들어,

function _curryr(fn) {
   return function(a, b) {
     return arguments.length == 2 ? fn(a, b) : function(b) { return fn(b, a); };
   }
 }
 
function _each(list, iter) {
    var keys = _keys(list);
    for (var i = 0, len = keys.length; i < len; i++) {
        iter(list[keys[i]], keys[i]);
    }
    return list;
}

var slice = Array.prototype.slice;
function _rest(list, num) {
  return slice.call(list, num || 1);
}

function _reduce(list, iter, memo) {
  if (arguments.length == 2) {
    memo = list[0];
    list = _rest(list);
  }
  _each(list, function(val) {
    memo = iter(memo, val);
  });
  return memo;
}

var users = [
    { id: 10, name: 'ID', age: 36 },
    { id: 20, name: 'BJ', age: 32 },
    { id: 30, name: 'JM', age: 32 },
    { id: 40, name: 'PJ', age: 27 },
    { id: 50, name: 'HA', age: 25 },
    { id: 60, name: 'JE', age: 26 },
    { id: 70, name: 'JI', age: 31 },
    { id: 80, name: 'MP', age: 23 },
    { id: 90, name: 'FP', age: 13 }
];

var user2 = {
  36: [{ id: 10, name: 'ID', age: 36 }],
  32: [{ id: 20, name: 'BJ', age: 32 }, { id: 30, name: 'JM', age: 32 }]
}

이렇게 그룹이 지어진 값이 리턴된다.

구현을 해보자.

var _group_by = _curryr(function(data, iter) {
  return _reduce(data, function(grouped, val) {
    var key = iter(val);
    (grouped[key] = grouped[key] || []).push(val);
    return grouped;
  }, {});
});

_group_by(users, function(user) {
  return user.age;
});

curryr인자로

function(data, iter) {
  return _reduce(data, function(grouped, val) {
    var key = iter(val);
    (grouped[key] = grouped[key] || []).push(val);
    return grouped;
  }, {});
}

function을 주게되고, group_by는

function(a, b) {
     return arguments.length == 2 ? fn(a, b) : function(b) { return fn(b, a); };
   }

함수를 리턴 받게 된다.

_group_by(users, function(user) {
  return user.age;
});

를 실행하게 되면 data는 users가 되고, key값을 정하는 iter함수는

function(user) {
  return user.age;
}

가 된다. 결국 'age'라는 키를 가진 값들이 키값이 되고, _reduce함수를 통해 users의 모든 값을 반복하며 비교하게 되고,

(grouped[key] = grouped[key] || []).push(val);

부분을 통해서 같은 값 끼리 배열이 생성된다.

위 함수를 좀 더 간결하게

function _push(obj, key, val) {
  (obj[key] = obj[key] || []).push(val);
  return obj;
}

var _group_by = _curryr(function(data, iter) {
  return _reduce(data, function(grouped, val) {
    return _push(grouped, iter(val), val)
  }, {});
});

로 변경이 가능하다.

응용해서 10대, 20대, 30대로 나눈다면,

_group_by(users, function(user) {
  return user.age - user.age % 10;
});

이렇게 실행도 가능하게 된다.

count_by

var _count_by = _curryr(function(data, iter) {
  return _reduce(data, function(count, val) {
    
  }, {});
});

값을 증가시키는 일을 안에서 해주면 되는데, 계속해서 이렇게 접기를 만들때, for문을 머리속에서 지우고 진행해야한다.
reduce를 하면서 안에 있는 모든 값들을 돌면서, 특정 함수를 한번씩 실행하면 결과가 나올 것이다라고 가정하고 프로그래밍을 한다.

var _count_by = _curryr(function(data, iter) {
  return _reduce(data, function(count, val) {
    var key = iter(val);
    count[key] ? count[key]++ : count[key] = 1;
    return count;
  }, {});
});

_count_by(users, function(user) {
  return user.age;
});
profile
개발자준

0개의 댓글