Computer >> 컴퓨터 >  >> 프로그래밍 >> JavaScript

JavaScript로 중첩 배열에서 최댓값 찾는 방법 (재귀 함수 예제)


숫자가 임의의 깊이까지 중첩되어 들어 있는 배열이 주어졌을 때, 그 안에서 가장 큰 숫자를 찾아 반환하는 간단한 JavaScript 함수를 작성한다고 가정해 보겠습니다.

const arr = [
    15, 24,
    [
        29, 85, 56,
        [
            36, 14, 6, 98, 34, 52
        ],
        22
    ], 87, 60
];

예를 들어 다음과 같은 입력 배열이 주어진다면,

const arr = [
    34, 65, 67,
    [
        43, 76, 87, 23, 56, 7,
        [
            54, 7, 87, 23, 79, 994, 2
        ],
        54
    ], 54, 4, 2
];

함수는 배열 전체에서 가장 큰 값인 다음 결과를 반환해야 합니다.

994

접근 방식: 재귀(Recursion) 활용

중첩의 깊이가 정해져 있지 않기 때문에 단순한 반복문만으로는 모든 요소를 탐색할 수 없습니다. 이럴 때 가장 효과적인 방법은 재귀 함수입니다. 배열의 각 요소를 순회하다가 요소가 배열이면 자기 자신을 다시 호출해 내부를 탐색하고, 숫자라면 현재까지의 최댓값과 비교하는 방식입니다.

핵심 로직 정리

  • 초기 최댓값은 어떤 숫자보다도 작은 -Infinity로 설정합니다.
  • 요소가 배열인지 Array.isArray()로 판별합니다.
  • 배열이면 재귀 호출로 내부 배열의 최댓값을 구해 현재 최댓값과 비교·갱신합니다.
  • 숫자라면 현재 최댓값보다 클 경우 값을 갱신합니다.
  • 순회가 끝나면 누적된 최댓값을 반환합니다.

예제 코드

다음은 전체 구현 코드입니다.

const arr = [
    34, 65, 67,
    [
        43, 76, 87, 23, 56, 7,
        [
            54, 7, 87, 23, 79, 994, 2
        ],
        54
    ], 54, 4, 2
];

const getGreatest = (arr, greatest = -Infinity) => {
    for (let i = 0; i < arr.length; i++) {
        // 요소가 배열이면 재귀 호출로 내부 최댓값을 구해 갱신
        if (Array.isArray(arr[i])) {
            greatest = getGreatest(arr[i], greatest);
            continue;
        }
        // 숫자라면 현재 최댓값과 비교
        if (arr[i] > greatest) {
            greatest = arr[i];
        }
    }
    return greatest;
};

console.log(getGreatest(arr));

주의: 중첩 배열을 만났을 때 return getGreatest(...)처럼 곧바로 반환하면 해당 배열 뒤에 남아 있는 나머지 요소들을 검사하지 못하게 됩니다. 위 코드처럼 재귀 호출의 결과를 greatest 변수에 누적한 뒤 순회를 계속하는 것이 안전합니다.

출력 결과

콘솔에는 다음과 같은 결과가 출력됩니다.

994

대안: flat()과 Math.max() 활용하기

모든 중첩을 한 번에 펼친 뒤 처리하는 더 간결한 방법도 있습니다.

const greatest = Math.max(...arr.flat(Infinity));
console.log(greatest); // 994

flat(Infinity)는 배열을 완전히 평탄화하므로 중첩 깊이를 신경 쓰지 않고 Math.max()로 최댓값을 바로 구할 수 있습니다. 다만 배열의 크기가 매우 클 경우 스프레드 연산자의 인수 개수 제한으로 인한 오류가 발생할 수 있으므로, 대용량 데이터에는 앞서 소개한 재귀 방식이 더 적합합니다.

마무리

재귀 함수를 활용하면 중첩 깊이에 상관없이 배열의 모든 요소를 빠짐없이 탐색할 수 있습니다. 데이터 양과 상황에 따라 재귀 방식과 flat() 기반 방식 중 적절한 방법을 선택해 사용하시기 바랍니다.