배열을 다루다 보면, 그륩핑을 해야하는 경우가 있다.
뭐 그러다 보면 아래처럼 불편한 코드가 생성 될 것이다.
const list = [
{class: 'a', score:1 },
{class: 'a', score:2 },
{class: 'a', score:3 },
{class: 'a', score:4 },
{class: 'b', score:1 },
{class: 'b', score:1 },
]
const group = {};
for (const item of list) {
group[item.class] = group[item.class] || []
group[item.class].push(item)
}
console.log('group', group)
뭐 reduce를 사용 하게 되면 아래 코드 처럼 되겟지...
const list = [
{class: 'a', score:1 },
{class: 'a', score:2 },
{class: 'a', score:3 },
{class: 'a', score:4 },
{class: 'b', score:1 },
{class: 'b', score:1 },
]
const group = list.reduce( (groupRes, item) => {
groupRes[item.class] = groupRes[item.class] || []
groupRes[item.class].push(item)
return groupRes
}, {} )
console.log('group', group)
둘 중에 어떤 방법을 쓰더라도, 코드가 길어진다는 것은 보는 사람 입장에서는 불편할 수 밖에는 없다.
그 와중에 좋은 함수가 보여서 공유한다.
const group = Object.groupBy(list, item => item.class)
console.log('group', group)
아주 깔끔한 코드가 되어버렸다.
하지만 여기서 문제가 발생한다. Object.groupBy의 결과 값은 null타입의 객체이다. null타입이 무슨 말일까?
뭐 다들 자바스크립트가 protoType기반의 객체지향 언어라는 것은 알 것이다.
const a = [1, 2, 3]
console.log(a.toString()) // 1,2,3
a.__proto__ = null
console.log(a.toString()) // Uncaught TypeError: a.toString is not a function
메서드가 다 없어진다... 자 이제 group을 보자.
console.log(group.toString) // undefined
console.log(group.constructor) // undefined
group또한 마찬가지이다. 자 그러면 대안을 보자.
const list = [
{class: 'a', score:1 },
{class: 'a', score:2 },
{class: 'a', score:3 },
{class: 'a', score:4 },
{class: 'b', score:1 },
{class: 'b', score:1 },
]
const group = Map.groupBy(list, item => item.class)
console.log('group', group)
console.log(group.toString()) // [object Map]
console.log(group.constructor) // ƒ Map() { [native code] }
자... 여기서 자바스크립트는 또 사람 헷갈릴만한 함수를 만들어 버렸다. 언젠간 window.isNaN vs Number.isNaN 에 대한 포스팅을 작성 하였다.
Object.Map을 null타입의 객체로 리턴 하는 건 좀..... 여기에 또 불편한 점이 또 있다.
아직 까지는 Map을 순회하여, 새로운 맵을 만들수가 없다는 것이다. Map은 펑터가 아니다....
무슨말일까? 저렇게 group을 만들어서 각 반의 scoreSum을 만들기 위해서는 어떻게 해야 할까?
lodash를 잠깐 꺼내보자.
const list = [
{class: 'a', score:1 },
{class: 'a', score:2 },
{class: 'a', score:3 },
{class: 'a', score:4 },
{class: 'b', score:1 },
{class: 'b', score:1 },
]
_(list).groupBy('class').mapValues((stuList) => _.sumBy(stuList, 'score')).value() // {a: 10, b: 2}
즉 위에서 보이는 mapValues가 없어서 아쉽다라는 것이다.
아마 이제 groupBy가 나왔으니.... 그륩핑만 필요한거 아니면, Map의 Map.prototyp.map함수가 추가 되지 않을 까 싶다.
댓글
댓글 쓰기