JavaScript에서 중첩된(nested) 배열을 받아 모든 요소를 하나의 평면적인 배열로 만들어 반환하는 함수를 작성해야 하는 경우가 자주 있습니다.
예를 들어 다음과 같습니다.
// 입력이 다음과 같다면:
const arr = [[1, 2, 3], [4, 5], [6]];
// 출력은 이렇게 되어야 합니다:
const output = [1, 2, 3, 4, 5, 6];
즉, 여러 겹으로 감싸인 배열의 모든 요소를 꺼내어 하나의 배열에 담는 '배열 평탄화(flattening)' 작업입니다. 그럼 이 기능을 구현하는 두 가지 방법을 살펴보겠습니다.
방법 1: 재귀(Recursion) 사용
이 방법은 원본 중첩 배열을 순회하면서, 요소가 배열이면 재귀적으로 다시 평탄화한 뒤 새로운 배열에 추가하는 방식입니다.
예제 코드
const arr = [[1, 2, 3], [4, 5], [6]];
const flatten = function(){
let res = [];
for(let i = 0; i < this.length; i++){
if(Array.isArray(this[i])){
res.push(...this[i].flatten());
} else {
res.push(this[i]);
};
};
return res;
};
Array.prototype.flatten = flatten;
console.log(arr.flatten());
코드의 동작 원리는 다음과 같습니다.
- Array.isArray()로 현재 요소가 배열인지 확인합니다.
- 배열이라면 해당 배열에 대해 flatten()을 재귀 호출하여 내부 요소를 펼친 후 push(...spread)로 결과 배열에 넣습니다.
- 배열이 아니라면 그대로 결과 배열에 추가합니다.
방법 2: Array.prototype.reduce() 사용
두 번째 방법은 reduce() 메서드를 활용하여 새로운 배열을 만드는 것입니다. 코드가 더 간결하고 함수형 스타일에 가깝습니다.
예제 코드
const arr = [[1, 2, 3], [4, 5], [6]];
const flatten = function(){
return this.reduce((acc, val) => {
return acc.concat(...val);
}, []);
};
Array.prototype.flatten = flatten;
console.log(arr.flatten());
여기서는 빈 배열 []을 초기값으로 설정한 뒤, 각 하위 배열을 concat(...val)으로 누적 배열(acc)에 이어 붙이는 방식으로 동작합니다.
출력 결과
두 방법 모두 콘솔에 동일한 결과가 출력됩니다.
[ 1, 2, 3, 4, 5, 6 ]
참고: Array.prototype.flat()
참고로 ES2019(ES10)부터는 JavaScript에 기본 내장된 flat() 메서드를 사용할 수도 있습니다. 예를 들어 arr.flat(Infinity)를 호출하면 임의의 깊이까지 한 번에 평탄화되므로, 최신 환경에서는 별도의 함수를 정의하지 않아도 됩니다.