문제 상황
JavaScript에서 두 개의 중첩(nested) 배열 arr1과 arr2를 인자로 받아, 두 배열의 모든 요소를 하나의 1차원 배열로 평탄화(flatten)한 새로운 배열을 반환하는 함수를 작성해야 합니다.
예를 들어 함수에 다음과 같은 입력이 주어졌다고 가정해 보겠습니다.
const arr1 = [
1, [
2, [
4, 5, [
6
]
]
]
];
const arr2 = [
11, 12, [
16, 18, [
19, 21, [
23
]
]
]
];이 경우 기대하는 출력 결과는 다음과 같습니다.
const output = [1, 2, 4, 5, 6, 11, 12, 16, 18, 19, 21, 23];
재귀를 활용한 해결 방법
중첩의 깊이가 정해져 있지 않기 때문에 재귀(recursion)를 사용하는 것이 가장 효과적입니다. 배열의 각 요소를 순회하면서 해당 요소가 배열이면 다시 자기 자신을 호출하고, 그렇지 않으면 결과 배열에 추가하는 방식입니다.
다음은 전체 코드입니다.
const arr1 = [
1, [
2, [
4, 5, [
6
]
]
]
];
const arr2 = [
11, 12, [
16, 18, [
19, 21, [
23
]
]
]
];
const flattenAndMerge = (arr1 = [], arr2 = []) => {
const res = [];
const flatten = (arr = []) => {
for(let i = 0; i < arr.length; i++){
if(Array.isArray(arr[i])){
// 요소가 배열이면 재귀 호출로 더 깊이 탐색
flatten(arr[i]);
} else if(typeof arr[i] === 'number'){
// 일반 값이면 결과 배열에 추가
res.push(arr[i])
};
};
};
flatten(arr1);
flatten(arr2);
return res;
};
console.log(flattenAndMerge(arr1, arr2));코드 동작 원리
위 코드의 핵심 로직은 다음과 같습니다.
- 결과 저장소 생성: 최종적으로 모든 요소가 담길 빈 배열
res를 먼저 선언합니다. - 재귀 함수 정의: 내부 함수
flatten은 전달받은 배열을 순회하며 각 요소를 검사합니다. - 배열 판별:
Array.isArray()로 요소가 배열인지 확인하고, 배열이라면 같은 함수를 재귀적으로 호출하여 내부까지 탐색합니다. - 값 추가: 배열이 아닌 숫자 값은
push()를 통해 결과 배열에 순서대로 저장됩니다.
실행 결과
콘솔 출력 결과는 다음과 같습니다.
[
1, 2, 4, 5, 6,
11, 12, 16, 18, 19,
21, 23
]참고: Array.prototype.flat() 활용하기
ES2019(ES10)부터는 flat() 메서드를 사용해 더 간단하게 구현할 수도 있습니다. 깊이를 무제한으로 지정하려면 Infinity를 인자로 넘기면 됩니다.
const flattenAndMerge = (arr1 = [], arr2 = []) =>
[...arr1.flat(Infinity), ...arr2.flat(Infinity)];이 방법은 코드가 훨씬 간결하지만, 문자열 등 특정 타입만 필터링하는 세부 제어가 필요하다면 앞서 소개한 재귀 방식이 더 유연합니다. 상황에 맞게 적절한 방법을 선택하시기 바랍니다.