Chapter 1 . 재귀함수 연습 + 복습
어떠한 특정 조건에 걸려서 멈추기 전까지 계속 나를 부르는 재귀함수를 이용해서 다양한 예제를 연습해보았습니다.
# Solve_flattenArr
* 함수 flattenArr을 재귀함수의 형태로 작성하여, 입력받은 다차원 배열을 1차원 배열로 리턴하세요.
- Array Method flat(), flatMap() 사용 금지
- 반복문(for,while) 사용 가능.
- 원본 배열 변경 금지
- 빈 배열을 입력 받은 경우는 빈 배열 리턴
예시를 생각해보면 다음과 같이 입력을 받고 출력을 해야 합니다.
1) 입력 : [ [1], 2, [3, 4], 5]
2) 출력 : [ 1, 2, 3, 4, 5]
배열 안에 배열이 있는 입력 이므로, 반복문으로 배열을 계속 (재귀) 돌다가 배열을 만나면 스프레드로 뿌려서 합쳐버릴 수 있게 만들 수 있습니다. ** 반복문 안에 요소가 배열일 경우와 배열이 아닐 경우로 구분하기 위해 배열을 구분해주는 Array.isArray() 메소드를 사용합니다. let result = []; 의 선언은 원본 배열을 해치지 않고 새로 생성한 result 배열 안에 1차원 배열을 집어 넣기 위해 생성했습니다. 저도 무의식중에 실수하는 것 이지만 result 배열은 재할당이 계속 일어나야 하므로 let으로 선언 하는 것을 주의해주세요.
function flattenArr(arr) {
// 1. 수행 조건 중 빈 배열을 입력 받은 경우, 빈 배열 리턴
if(arr.length === 0) {
return [];
}
// 2. 반복문
let result = [];
for( let i = 0 ; i < arr.length; i++){
// ** 요소가 배열이 아닐 경우,
if( !Array.isArray(arr[i]) ){
//To DO
}
// ** 요소가 배열일 경우
else{
//To Do
}
}
}
이제 각각 조건안의 코드를 작성해봅시다. 요소가 배열이 아닌 경우는 그대로 새 배열에 push( )를 사용하여 넣어주면 됩니다.
//생략
if( !Array.isArray(arr[i]) ){
result.push(arr[i])
}
요소가 배열인 경우에는 해당 배열인 요소를 스프레드 메소드를 사용하여 새로운 배열에 똑같이 push( )로 넣어주면 됩니다. 다만 주의해야 할 점은 다차원 배열이 단순히 배열 안에 배열로 끝나는 것이 아니라 배열 안에 배열 안에 배열 안에... 이렇게 다중 중첩 되어있는 상태일 수도 있으니 이때 재귀함수 : 내가 만든 함수 flattenArr(arr) 로 계속 돌릴 수 있게 넣어주어야 합니다.
//생략
else{
//const flatten = flattenArr(arr[i]);
//위처럼 선언해서 push(...flatten)을 넣어주어도 됩니다.
result.push(...flattenArr(arr[i]));
}
return result
flattenArr 재귀함수는 요소를 계속 돌다가 더이상 배열 안에 배열인 요소가 없는 상태가 되면 첫 번째 if 문의 조건에 의해 종료되어 for 문을 빠져나오고 최종적으로 새로 만들어진 1차원 배열 result 를 return 함으로써 원하는 출력 값을 얻을 수 있습니다.
Chapter 1-2 . 번외 - 코딩테스트
※ 여기는 공부 중 - 추 후 업데이트 예정 ※
# 조합
연습 : stackblitz
# reduce : 배열의 요소들을 앞 뒤로 누적해서 더하거나 곱할 수 있게 하기
Chapter 2. Tree UI 구조
이러한 Tree UI 구조일 경우 HTML에서 나열하는 것이 아닌 js 파일에서 DOM과 재귀함수를 통해 작성을 할수 있습니다. <ul> 구조 안에 <li> 안에 <input><span><ul> 의 구조가 반복되는 Tree 구조 입니다. "createTreeView()"를 재귀함수로 이용해서 원하는 만큼 html에 data의 구조를 나열할 수 있습니다.
<ul>
.....┗ <li>....................음식
............┗ <input>
............┗ <span> // menu[i].name
............┗ <ul>
....................┗ <li> ...<li> // menu[i].children
.....┗<li>....................음료수
............┗ <input>
............┗ <span> // menu[i].name
............┗ <ul>
....................┗ <li> ...<li>
⇒ For문을 돌면서 각 구조의 DOM을 생성
const root = document.getElementById('root');
//currentNode : ul#root
function createTreeView(menu, currentNode) {
for(let i = 0; i < menu.length; i++){
const li = document.createElement('li');
const ul = document.createElement('ul');
const input = document.createElement('input');
input.setAttribute('type', 'checkbox')
const span = document.createElement('span');
span.textContent = menu[i].name;
}
}
createTreeView(menu, root);
⇒ if문 조건으로 menu객체 안의 속성 값에 children이 존재할 때와 존재하지 않을 대로 구분
** 따로 if문을 두지 않는다면 무한으로 UI 구조가 생성이 되겠죠. 이를 맊기 위해 menu 객체 안에 children이라는 속성이 없는 요소 (ex. 각 부분의 마지막 <li>)를 만나게 된다면 더이상 생성하지 않고 단순히 속성 값을 출력하라는 지시가 필요합니다.
for(let i = 0; i < menu.length; i++){
//생략
if(menu[i].children){ // menu[i]에 key가 children이 존재 할 때,
li.append(inputTag);
li.append(spanTag);
li.append(ulTag);
createTreeView(menu[i].children, ul);
}
else { // menu[i]에 key가 children이 존재하지 않을 때,
li.textContent = menu[i].name; // li태그의 콘텐츠에 menu[i].name만 넣기
}
currentNode.append(li);
}
제가 첫 번째로 풀었던 댕망진창 코드 ㅎㅎ
const root = document.getElementById('root');
//currentNode : ul#root
function createTreeView(menu, currentNode) {
const span = document.createElement('span');
const input = document.createElement('input');
const ul = document.createElement('ul');
for( let i = 0 ; i < menu.length; i++){
// console.log(menu[i].name); //음료,음식,굿즈,카드
const li = document.createElement('li');
//base case
if(menu[i].children){
input.type = "checkbox";
span.textContent = menu[i].name;
li.appendChild(input);
li.appendChild(span);
// li.appendChild(ul);
li.appendChild(createTreeView(menu[i].children, ul))
}else {
li.textContent = menu[i].name;
}
currentNode.append(li);
// createTreeView(menu[i].children, ul);
// ul.appendChild(createTreeView(menu[i].children), ul)
// recursive case
// if(menu[i].children === undefined){
// li.textContent = menu[i].name
// }
}
return currentNode;
}
IF you want to learn more about the recursion, plus click the below link.
'일상의 기록 > 🌷DAILY 회고록 : 코드스테이츠' 카테고리의 다른 글
[230418] Storybook 과 useRef (0) | 2023.04.18 |
---|---|
[230413] UI와 UX 찍먹 (0) | 2023.04.13 |
[230410] Section 02 회고 : 스스로에게 실망.. (0) | 2023.04.10 |
[230406 ~7] Node.js와 Express를 이용해 아주아주 간단하게 서버를 찍먹해보았다. (0) | 2023.04.06 |
[230404 ~ 5] 아주 살짝 Web server 찍먹해보기 (0) | 2023.04.04 |