JavaScript/알고리즘

프로그래머스 컨트롤 제트 JS (while문을 통해 findIndex()여러번 처리 / 빈배열이 호출되면 에러가 나는 reduce() )

hihiha2 2023. 6. 14. 17:55
반응형

문제 설명

숫자와 "Z"가 공백으로 구분되어 담긴 문자열이 주어집니다. 문자열에 있는 숫자를 차례대로 더하려고 합니다. 이 때 "Z"가 나오면 바로 전에 더했던 숫자를 뺀다는 뜻입니다. 숫자와 "Z"로 이루어진 문자열 s가 주어질 때, 머쓱이가 구한 값을 return 하도록 solution 함수를 완성해보세요.

 

 

🙋‍♀️ 내 생각

보고 바로 reduce를 이용해서 값을 더해야겠다는 생각이 들었다.

문제는 Z가 있으면 바로 앞의 숫자를 빼는것을 어떻게 처리할 것인가였다.

생각나는 방법은 두가지였는데,

1️⃣Z를 바로 앞의값의 -인값으로 치환 2️⃣ Z가 있으면 바로 앞의 값과 Z를제거

였다.

둘다 인덱스로 바로 앞의 값에 접근하는것은 같다.

나는 둘중에 2️⃣번방법으로 문제를 풀었다.

 

 

✅ 내 코드

function solution(s) {
   let arr = s.split(' ')
   while (arr.includes("Z")){
     const index = arr.findIndex((e) => e === "Z");
    arr.splice(index-1, 2);
   }
    return arr.reduce((acc,cur)=> acc+Number(cur),0)
}

우선 문자열을 배열로 만들어야하기 때문에 split()을 사용했다. 공백을 기준으로 나눠야해서 split(' ')로 구분자를 넣어주었다.

 

그런다음 Z를 포함하고 있는것만 처리해야하기 때문에 while문을 사용했다.

while은 주어진 조건이 참인경우 반복적으로 코드를 수행하기때문에 이런 방법을 이용하면 Z의 값이 여러번 방법되어 나와도 원하는 결과를 얻을 수 있다.

 

굳이 while문을 이용해서 반복적인 수행을 하도록 만든 이유는 findIndex때문이다. 

findIndex()는 찾고자하는 값의 인덱스를 찾을때 사용하는 메서드인데, 조건을 충족하는 첫번째 인덱스만을 반환하기 때문에 while문을 쓰지 않으면 처음만나는 Z값의 인덱스만을 찾고 끝난다. 그래서 while문을 통해서 여러개의 Z를 만나더라도 반복해서 인덱스를 찾을 수 있게 한다.

 

arr에서 찾는 값이 Z이면 인덱스를 찾도록 한뒤, const index = arr.findIndex((e) => e === "Z")

splice()를 이용해서 해당하는 인덱스의 값들을 제거한다. arr.splice(index-1, 2)

splice(시작인덱스, 제거할 요소의 수)이므로 시작인덱스를 (Z의 인덱스-1)로 잡고 제거할 요소의 수를 2로 잡아서 이전값과 Z를 모두 제거한다.

 

while이 반복되면서 이렇게 Z와 Z앞의 값은 모두 제거되고, 나머지만 배열안에 남는다.

더이상 Z를 포함하지 않을때 while문에 빠져나온다. (arr.includes("Z"))의 값이 false가 되기때문)

 

그런 다음 배열안에 남아있는 값들을 reduce()를 통해서 더해주는데 안의 값들은 아직 string이기 때문에 cur에 Number()를 처리해서 값들을 모두 숫자로 바꾸면서 더해주도록 처리한다. 

 

 

 

💻 내가 사용한 메서드

findIndex():충족하는 배열의 첫 번째 요소 인덱스를 반환. 테스트 기능을 만족하는 요소가 없으면 -1이 반환

Array.findIndex()

 

🔫 주의

충족하는 첫번째 인덱스만을 반환하므로 주의해야한다. 만족하는 모든 값을 다 찾는건 아니다.

위에서 푼것과 같이 이런 문제점을 해결하기 위해서 while문을 통해서 여러개의 충족하는 값들의 인덱스를 모두 찾을 수도 있다.

 

 

 

splice(): 배열의 기존 요소삭제 또는 교체하거나 새 요소를 추가하여 배열의 내용을 변경

Array.splice()

    array.splice(start[, deleteCount[, item1[, item2[, ...]]]])

start: 배열의 변경을 시작할 인덱스

deleteCount: 배열에서 제거할 요소의 수

item: 배열에 추가할 요소

 

splice()는 slice()와 다르게 원본을 변경하므로 주의해야한다.

 

 

💻  다른사람 코드중에 배울 것

function solution(s) {
    const stack = []

    s.split(' ').forEach((target) => {
        if(target === 'Z') stack.pop();
        else stack.push(+target)
    })

    return stack.length ? stack.reduce((pre, cur) => pre + cur) : 0;
}

stack이라는 빈 배열을 만들어주고 pop()push()를 이용해서 필요한 값만으로 채워나가는 방식이다.

처음에 문제를 봤을때 pop()을 이용해서 풀수있지 않을까했는데 그렇게 푼 방식이어서 공부해보았다.

 

우선 stack이라는 빈배열을 만든다.

 

s.split(' ')으로 문자열을 공백을 기준으로 나눈 뒤, 배열로 만들고 forEach를 통해서 각각의 요소를 돌면서 특정동작을 수행하도록 한다.

특정동작은 if문을 통해서 만약 요소의 값이 Z라면 stack.pop()을 하도록 한다. pop()은 배열의 가장 마지막 값을 제거하는 기능을 하므로 Z를 만나면 이전의 값을 제거할 것이다. 그리고 Z는 배열에 담기지 않는다. (else를 통해서만 push되도록 해주었기때문)

 

만약 요소가 Z가 아니라면 stack.push(+target)을 통해서 배열의 맨 마지막에 요소가 추가되는데 +를 통해서 숫자로 변환된 값이 push되게 한다.

 

forEach를 통해서 배열을 다 돌고 난뒤에 stack.length를 이용해서 빈배열인 경우를 처리해준다.

🔫 새롭게 알게된 것

reduce()빈 배열에 대해서 호출될 경우 에러를 던지는 동작을 가지고 있다.

➡️ 스택이 비어있는 경우에 대한 처리가 필요하다.

 

stack의 길이를 검사해서 만약 길이가 0이라면(스택이 비어있다면), 0을 리턴하도록 처리를 해주었다.

 

그리고 빈배열이 아니라면, reduce를 통해서 값을 더한다.

 

 

 

 

🙋‍♀️ 내 생각

reduce()빈배열을 호출할 경우에 에러를 발생시킨다는 것은 이번문제를 통해서 처음 알았다. 다음번에 reduce를 이용해서 코드를 짤때 이런 예외처리를 해주어야겠다.

 

findIndex()나 find()처럼, 자바스크립트 메서드중에는 해당하는 첫번째 요소만을 처리하고 넘어가는 메서드들이 많다.

이런 경우 while문을 통해서 여러번 처리하고 싶은 동작을 반복할 수 있도록 해줄 수 있다. 

 

문제를 풀면서 메서드에 대한 이해도가 높아지는 것 같아서 좋다. 자바스크립트에 대한 이해도가 올라갈수록 평소 프로젝트를 할때도 더 이해하면서 코드를 짜고 더 좋은 코드도 나올 수 있지 않을까 생각한다.

 

전에 find()를 통해서 코드를 짰던 기억이 있어서 이 문제를 풀면서 다시 한번 코드를 생각해보았다.

 const { id } = useParams<{ id: string }>();

  // 해당 ID에 해당하는 데이터 찾기
  const mbtiFixData = mbtiEach.find((item) => item.id === Number(id));

이 코드는 useParams()훅을 사용하여 URL매개변수에서 id값을 추출하고, 해당 id를 mbtiEach 배열에서 일치하는 데이터를 찾는부분이다.

(useParams()는 값이 string으로만 들어오기 때문에 Number(id)로 숫자로 타입을 변환하여 비교하도록 하였다)

 

return문안에서 값의 활용은 아래와 같이 한다. 비교하여 일치하는 데이터의 title과 src를 화면에 띄우도록 하였다.

    <div>{mbtiFixData.title}</div>
    <img alt="mbtiPhoto" src={mbtiFixData.src} />

 

 

알고리즘 문제를 풀면서 이런 코드도 더 잘 읽히고 어떻게 활용해야할지가 잘 보이는것같아서 앞으로 프로젝트를 만들때 도움이 되지 않을까 생각한다. 뭐든 기초가 탄탄해야한다는 말이 맞는것같다. 

 

반응형