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

JavaScript – 중첩 배열을 중첩된 순서 없는 목록(ul)으로 변환하는 방법

문제 소개

다음과 같이 문자열 값과 배열이 섞여 있는 중첩 배열(nested array)이 있다고 가정해 보겠습니다.

const arr = [
  'Value 1', ['Inner value 1', 'Inner value 2', 'Inner value 3', 'Inner value 4'],
  'Value 2', 'Value 3', 'Value 4', 'Value 5', 'Value 6'
];

우리가 작성해야 할 프로그램은 이처럼 임의의 깊이로 중첩된 배열을 받아 HTML의 중첩된 순서 없는 목록(<ul>)으로 변환하는 자바스크립트 코드입니다.

여기서 유일하게 주의할 점은 ul의 중첩 구조가 반드시 원본 배열의 중첩 구조와 정확히 동일해야 한다는 것입니다. 즉, 배열 안에 배열이 발견되면 그 위치에 하위 목록이 생성되어야 합니다.

접근 방식: 재귀 함수 활용

배열이 몇 단계나 중첩될지 미리 알 수 없기 때문에, 재귀(recursion)를 사용하는 것이 가장 깔끔한 해결책입니다. 전체적인 로직은 다음과 같습니다.

  • 컨테이너(루트 요소) 안에 새로운 ul 요소를 생성합니다.
  • 배열의 각 요소를 순회하면서 Array.isArray()로 타입을 검사합니다.
  • 요소가 배열이라면 직전에 만든 li를 부모로 삼아 함수를 재귀 호출하여 하위 목록을 만듭니다.
  • 요소가 일반 값이라면 li를 생성하고 텍스트 노드를 추가한 뒤 ul에 붙입니다.

구현 예제

자바스크립트 코드

const arr = [
  'Value 1', ['Inner value 1', 'Inner value 2', 'Inner value 3', 'Inner value 4'],
  'Value 2', 'Value 3', 'Value 4', 'Value 5', 'Value 6'
];
const prepareUL = (root, arr) => {
  let ul = document.createElement('ul');
  let li;
  root.appendChild(ul);
  arr.forEach(function(item) {
    if (Array.isArray(item)) {
      prepareUL(li, item);
      return;
    };
    li = document.createElement('li');
    li.appendChild(document.createTextNode(item));
    ul.appendChild(li);
  });
}
const div = document.getElementById('myList');
prepareUL(div, arr);

HTML 코드

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div id="myList"></div>
</body>
</html>

코드 설명

prepareUL 함수는 두 개의 인자를 받습니다. 첫 번째는 목록이 삽입될 부모(root) DOM 요소이고, 두 번째는 변환 대상인 배열입니다. 함수 내부에서는 먼저 ul 요소를 생성해 루트에 추가한 후, forEach로 배열의 모든 요소를 순회합니다. 이때 Array.isArray(item)이 true라면 해당 항목은 하위 배열이므로, 가장 최근에 생성된 li를 기준점으로 prepareUL을 다시 호출합니다. 이 과정이 배열의 깊이만큼 반복되면서 원본 배열의 중첩 구조가 그대로 ul/li 계층 구조로 재현됩니다.

실행 결과

위 코드를 실행하면 배열의 계층 구조가 그대로 반영된 중첩 목록이 화면에 렌더링됩니다.

JavaScript – 중첩 배열을 중첩된 순서 없는 목록(ul)으로 변환하는 방법