자바스크립트 reduce 함수 10가지 예제
안녕하세요?
자바스크립트 코드를 짤 때 우리가 보통 forEach, map, filter, indexOf는 자주 쓰지만 reduce 함수는 잘 안 쓰는데요.
원인은 어렵기 때문이죠.
사실 자바스크립트 고수분들은 reduce 함수를 잘 쓰는데요.
다음 10가지 예제를 보시고 원하시는 상황에 적용해서 쓰면 좋을 듯합니다.
reduce 기초
reduce(callbackFn)
reduce(callbackFn, initialValue)
위와 같이 reduce 함수는 콜백 함수 또는 initialValue를 가지는데요.
콜백 함수는 또 accumulator, currentValue, currentIndex, array를 또 가집니다.
그럼 예제를 통해 reduce 함수를 좀 더 알아보겠습니다.
2차원 배열을 1차원 배열로 변환하기
const array_0 = [
[1, 1],
[2, 3],
[3, 5],
].reduce(
(accumulator, currentValue) => accumulator.concat(currentValue),
[], // initial value
)
// array_0: [ 1, 1, 2, 3, 3, 5 ]
reduce와 concat 함수를 이용해서 쉽게 2차원 배열을 1차원 배열로 전환했습니다.
다차원 배열을 1차원 배열로 변환하기
위에서는 2차원 배열을 1차원 배열로 변환했었는데요, 사실 2차원 배열 말고 다차원 배열을 1차원 배열로 변환할 수 있습니다.
function ReduceArray(arr = []) {
return arr.reduce(
(accumulator, currentValue) =>
accumulator.concat(
Array.isArray(currentValue) ? ReduceArray(currentValue) : currentValue,
),
[],
)
}
const array_1 = ReduceArray([
[1, [1, 2]],
[3, [3, [5]]],
])
// array_1: [ 1, 1, 2, 3, 3, 5 ]
배열 안의 중복 항목 없애기
function UniqueArray(arr = []) {
return arr.reduce(
(accumulator, currentValue) =>
accumulator.includes(currentValue)
? accumulator
: [...accumulator, currentValue],
[],
)
}
const array_2 = UniqueArray([1, 1, 2, 3, 3, 5])
// array_2: [ 1, 2, 3, 5 ]
사실 위 코드는 자바스크립트의 Set 타입을 이용해서도 쉽게 구현할 수 있습니다.
const array_2 = [...new Set([1, 1, 2, 3, 3, 5])]
// array_2: [ 1, 2, 3, 5 ]
배열 분할하기
function SpiltArray(array, size) {
return array.reduce((acc, _, index) => {
if (index % size === 0) acc.push(array.slice(index, index + size))
return acc
}, [])
}
const numbers = [1, 2, 3, 4, 5, 6, 7]
const array_3 = SpiltArray(numbers, 2)
// array_3: [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ], [ 7 ] ]
객체를 URL 파라미터로 변환하기
function StringifyQueryParam(queryParam = {}) {
return Object.entries(queryParam)
.reduce(
(t, v) => `${t}${v[0]}=${encodeURIComponent(v[1])}&`,
Object.keys(queryParam).length ? '?' : '',
)
.replace(/&$/, '')
}
const queryString = StringifyQueryParam({
name: 'stringify',
email: 'stringify@gmail.com',
})
// queryString: '?name=stringify&email=stringify%40gmail.com'
URL 파라미터 파싱 하기
function ParseQueryString(queryString) {
return queryString
.replace(/(^\?)|(&$)/g, '')
.split('&')
.reduce((t, v) => {
const [key, val] = v.split('=')
t[key] = decodeURIComponent(val)
return t
}, {})
}
const queryParam = ParseQueryString(
'?name=stringify&email=stringify%40gmail.com',
)
// queryParam: { name: 'stringify', email: 'stringify@gmail.com' }
객체의 특정 항목을 배열로 그룹화하기
function GroupBy(array, property) {
return array.reduce((acc, obj) => {
let key = obj[property]
acc[key] = acc[key] || []
acc[key].push(obj)
return acc
}, {})
}
const users = [
{ name: 'Kim', age: 30 },
{ name: 'Park', age: 28 },
{ name: 'Lee', age: 28 },
]
const groupedUsers = GroupBy(users, 'age')
// groupedUsers:
// {
// '28': [ { name: 'Park', age: 28 }, { name: 'Lee', age: 28 } ],
// '30': [ { name: 'Kim', age: 30 } ]
// }
객체의 배열에서 특정 항목의 값 얻기
function ExtractValue(arr, property) {
return arr.reduce(function (acc, object) {
if (property in object) acc.push(object[property])
return acc
}, [])
}
const users = [
{ name: 'Kim', age: 30 },
{ name: 'Park', age: 28 },
{ name: 'Lee', age: 28 },
]
const names = ExtractValue(users, 'name')
// names: [ 'Kim', 'Park', 'Lee' ]
특정 값을 배열에 채우기
function FillValue(arr = [], val, start = 0, end = arr.length) {
if (start < 0 || start >= end || end > arr.length) return arr
return [
...arr.slice(0, start),
...arr.slice(start, end).reduce((t, v) => (t.push(val || v), t), []),
...arr.slice(end, arr.length),
]
}
const arr4 = FillValue([1, 2, 3], 'Kim')
// arr4: [ 'Kim', 'Kim', 'Kim' ]
const arr5 = FillValue([1, 2, 3], 'Kim', 1, 2)
// arr5: [ 1, 'Kim', 3 ]
const arr6 = FillValue([1, 2, 3], 'Kim', 1, 3)
// arr6: [ 1, 'Kim', 'Kim' ]
Promise 배열을 순차적으로 실행하기
const runPromisesInSeries = (ps, initialValue) =>
ps.reduce((p, next) => p.then(next), Promise.resolve(initialValue))
const fetchUserData = username => {
return new Promise(resolve => {
setTimeout(() => {
console.log('fetchUserData')
resolve({ name: username })
}, 500)
})
}
const renderUserInfo = user => {
return new Promise(resolve => {
setTimeout(() => {
console.log('renderUserInfo')
resolve(`<h1>${user.name}</h1>`)
}, 500)
})
}
const outputUserInfo = html => {
return new Promise(resolve => {
console.log('outputUserInfo')
resolve({ status: 'success', content: html })
})
}
const pSeries = runPromisesInSeries(
[fetchUserData, renderUserInfo, outputUserInfo],
'Bytefer',
)
pSeries.then(console.log)
지금까지 reduce 함수의 10가지 예제를 알아보았는데요.
필요하신 상황에 맞게 골라 쓰시면 좋을 듯합니다.
그럼.