문자열로 이루어진 중첩(nested) 배열이 있을 때, 이 배열과 검색할 문자열을 인자로 받아 해당 문자열이 중첩 배열 전체에서 몇 번 나타나는지 그 개수를 반환하는 함수를 작성해야 한다고 가정해 봅시다.
배열이 여러 깊이로 중첩되어 있기 때문에 단순한 반복문만으로는 해결할 수 없습니다. 이럴 때 재귀(recursion)를 활용하면 깊이에 상관없이 모든 요소를 탐색할 수 있습니다. 아래에서 코드를 살펴보겠습니다.
예제
const arr = [
"apple",
["banana", "strawberry", "dsffsd", "apple"],
"banana",
["sdfdsf", "apple", ["apple", ["nonapple", "apple", ["apple"]]]]
, "apple"];
const calculateCount = (arr, query) => {
let count = 0;
for (let i = 0; i < arr.length; i++) {
// 현재 요소가 검색 문자열과 일치하면 카운트 증가
if (arr[i] === query) {
count++;
continue;
}
// 현재 요소가 배열이라면 재귀 호출로 내부 탐색
if (Array.isArray(arr[i])) {
count += calculateCount(arr[i], query);
}
}
return count;
};
console.log(calculateCount(arr, "apple"));코드 설명
위 코드의 동작 원리는 다음과 같습니다.
1. 순회: for 반복문으로 배열의 각 요소를 하나씩 확인합니다.
2. 일치 여부 판단: 현재 요소가 검색 문자열(query)과 정확히 일치하면 count를 1 증가시키고 다음 요소로 넘어갑니다.
3. 재귀 탐색: 현재 요소가 배열인 경우 Array.isArray()로 판별한 뒤, 같은 함수를 재귀적으로 호출하여 하위 배열 내부도 탐색합니다. 반환된 값은 기존 카운트에 더해집니다.
이 방식 덕분에 배열이 몇 겹으로 중첩되어 있더라도 모든 문자열을 빠짐없이 검사할 수 있습니다.
출력 결과
콘솔에 출력되는 결과는 다음과 같습니다.
7
예제 배열에서 "apple"은 최상위 레벨에 2번, 첫 번째 하위 배열에 1번, 두 번째 하위 배열과 그 내부에 걸쳐 총 4번 나타나므로 최종 결과는 7이 됩니다. 참고로 "nonapple"은 "apple"과 완전히 일치하지 않으므로 카운트에 포함되지 않습니다.