JavaScript를 사용하다 보면 키 역할을 하는 문자열 배열과 값 역할을 하는 중첩 배열 두 개를 하나의 객체(JSON)로 합쳐야 하는 경우가 자주 있습니다. 예를 들어, 식사 이름 목록과 각 식사에 해당하는 재료 목록이 따로 있을 때, 이 둘을 하나의 객체로 깔끔하게 묶는 방법을 알아보겠습니다.
다음과 같은 두 개의 배열이 있다고 가정해 보겠습니다.
const meals = ["breakfast", "lunch", "dinner"]; const ingredients = [ ["eggs", "yogurt", "toast"], ["falafel", "mushrooms", "fries"], ["pasta", "cheese"] ];
우리가 작성해야 할 함수는 이 두 배열을 입력으로 받아, 두 번째 배열의 하위 배열들을 첫 번째 배열의 해당 문자열(키)에 매핑하는 역할을 해야 합니다.
따라서 위 배열에 대한 최종 출력 결과는 다음과 같은 형태가 되어야 합니다.
const output = {
"breakfast": ["eggs", "yogurt", "toast"],
"lunch": ["falafel", "mushrooms", "fries"],
"dinner": ["pasta", "cheese"]
};예제 코드
이를 구현한 코드는 다음과 같습니다.
const meals = ["breakfast", "lunch", "dinner"];
const ingredients = [
["eggs", "yogurt", "toast"],
["falafel", "mushrooms", "fries"],
["pasta", "cheese"]
];
const combineMealAndIngredient = (meals, ingredients) => {
const res = {};
meals.forEach(function (el, ind) {
this[el] = ingredients[ind];
}, res);
return res;
};
console.log(combineMealAndIngredient(meals, ingredients));코드 설명
핵심은 forEach 메서드의 두 번째 인자입니다. 여기에 res 객체를 전달하면 콜백 함수 내부의 this가 res 객체를 가리키게 됩니다. 그 결과 매번 새로운 객체를 참조하지 않고도 반복문 안에서 식사 이름을 키로, 해당 인덱스의 재료 배열을 값으로 손쉽게 할당할 수 있습니다.
더 간결한 대안: Object.fromEntries 활용하기
같은 결과를 한 줄로 처리하고 싶다면 ES2019에서 도입된 Object.fromEntries()와 map()을 조합하는 방법도 좋습니다.
const output = Object.fromEntries( meals.map((meal, i) => [meal, ingredients[i]]) ); console.log(output);
map()으로 [키, 값] 쌍의 배열을 만든 뒤 Object.fromEntries()에 넘기면 객체가 완성됩니다. 가독성이 뛰어나고 부수 효과(side effect) 없이 동작하기 때문에 실무에서도 널리 사용되는 패턴입니다.
출력 결과
두 방법 모두 콘솔에는 동일한 결과가 출력됩니다.
{
breakfast: [ 'eggs', 'yogurt', 'toast' ],
lunch: [ 'falafel', 'mushrooms', 'fries' ],
dinner: [ 'pasta', 'cheese' ]
}