-
reduce를 이용해 배열 객체를 하나의 객체로 만들기개발/Javascript 2022. 4. 26. 22:48
유저 정보를 객체 형태로 가지고 있는 다음 배열이 있습니다.
const arr = [{name : "kim", age : 20, gender : "male"}, {name : "lee", age : 21, gender : "female"}, {name : "park", age : 22, gender : "male"}];
이 배열을 이용해서 {kim : "male", lee : "female", park : "male"} 객체를 만들 수 있습니다.
배열의 요소가 객체일 때 특정 프로퍼티만 추출해서 하나의 객체로 만드는 방법이라고 생각하면 될 것 같습니다.
일단 map을 이용해 이름과 성별만으로 이루어진 배열을 만듭니다.
const mapResult = arr.map(person => ({[person.name] : person.gender})); // [ { kim: 'male' }, { lee: 'female' }, { park: 'male' } ]
reduce 함수를 이용하면 이 배열을 하나의 객체로 만들 수 있는데요.
먼저 reduce를 짧게 살펴봅시다.
reduce 함수의 인수로 사용되는 함수 리듀서(reducer, 콜백 함수)는 네 개의 인자를 가집니다.
1. 누산기
2. 현재 값
3. 현재 인덱스(optional)
4. 원본 배열(optional)
그리고 initialValue(optional)을 지정할 수 있는데요. 이는 누산기의 초기값을 말합니다.
따로 지정하지 않으면 배열의 첫 번째 요소가 initialValue가 됩니다.
reduce 함수는 빈 요소를 제외하고 배열 내에 존재하는 각 요소에 대해 콜백 함수를 한 번씩 실행합니다.
initialValue를 제공하면 누산기의 값은 initialValue이 되며 현재 값은 배열의 첫 번째 값이 됩니다.
initialValue를 제공하지 않았다면 누산기는 배열의 첫 번째 값이 되며 현재 값이 배열의 두 번째 값이 됩니다.
mdn에는 reduce를 이용해 배열 요소의 정수값을 합산하는 예제가 나와 있습니다.
const array1 = [1, 2, 3, 4]; // 0 + 1 + 2 + 3 + 4 const initialValue = 0; const sumWithInitial = array1.reduce( (previousValue, currentValue) => previousValue + currentValue, initialValue ); console.log(sumWithInitial); // expected output: 10
리듀서의 첫 번째 인자가 누산기입니다. initialValue가 주어졌으므로 최초에 previosValue에는 initialValue인 0이, currentValue에는 배열의 첫 번째 요소인 0이 들어가게 됩니다.
previousValue + currentValue 결과가 previousValue에 누적됩니다.
이 동작 원리를 이용해 객체를 요소로 하는 배열을 하나의 객체로 만들겠습니다.
const result = mapResult.reduce((a, b) => ({...a, ...b}), {});
화살표 함수에서 객체 리터럴을 반환할 때는 본문을 소괄호로 감싸야 합니다.
초기값이 빈 객체({})가 주어졌으므로 최초 누산기 값은 {}입니다.
b는 배열의 첫 번째 요소인 {kim : "male"}이기 때문에 첫 리듀서 호출 후 a는 {kim : "male"}입니다.
"..."은 스프레드 연산자 혹은 전개 구문으로, 말 그대로 객체 안의 값들을 퍼뜨립니다(전개합니다).
a는 빈 객체이므로 아무 프로퍼티가 전개되지 않으며 b를 전개하면 kim : "male"이 됩니다.
이를 객체 리터럴로 감쌌기 때문에 리듀서 호출 후 a는 {kim : "male"}입니다.
이 과정이 비어 있지 않은 배열 요소에 대해 순차적으로 반복됩니다.
1. { kim : "male" }
2. { kim : "male", lee : "female" }
3. { kim : "male", lee : "female", park : "male" }
const arr = [{name : "kim", age : 20, gender : "male"}, {name : "lee", age : 21, gender : "female"}, {name : "park", age : 22, gender : "male"}]; const mapResult = arr.map(person => ({[person.name] : person.gender})).reduce((a, b)=>({...a, ...b}), {});
'개발 > Javascript' 카테고리의 다른 글
[JavaScript] "Illegal invocation" errors (0) 2022.05.31 Response.json() (0) 2022.05.06 키보드 입력 (0) 2022.03.30 프로토타입 - 기본 (0) 2022.03.01 var, function (0) 2022.02.26