중간고사가 끝나고 여유가 생겨 오랜만에 코딩테스트 연습을 위해 프로그래머스에서 '올바른 괄호'라는 문제를 풀고 있었는데, 작성한 코드의 로직이 틀린 곳이 없음에도 특정 케이스가 계속 통과하지 않는 문제가 발생했습니다. 그래서 테스트케이스를 직접 작성해보고 코드도 디버깅해보며 오랜시간 전전긍긍하다 결국 문제점을 발견하고 해결했습니다. 이 문제점은 그동안 제가 전혀 몰랐던 내용이었기에, 이렇게 기록으로 남겨둡니다.
결론부터 말하면 자바스크립트의 배열을 순회하는 forEach문에서는 return문이나 break문을 작성해도 코드가 반복을 중단하지 않습니다. 그리고 forEach문 안에서 return문을 만나도 forEach문을 감싸고 있는 함수를 벗어나지 않습니다.
예시코드를 살펴보면 다음과 같습니다.
function solution(s){
s_arr = [...s];
stack = [];
s_arr.forEach((item) => {
if(item === "(") {
// push
stack.push(item);
} else {
// pop
if (stack.length === 0)
return false; // 주목!!
stack.pop();
}
})
if (stack.length !== 0) {
return false;
}
return true;
}
위 코드는 스택 자료구조의 대표적인 예제인 '올바른 괄호인지 판별'하는 문제입니다. solution 함수는 주어진 괄호 문자열이(예:"(())") 바르게 짝지어졌다면 true를, 그렇지 않으면 false를 반환하는 함수입니다.
여기서 주목해야 할 부분은 저 forEach문에서 false를 return하는 코드입니다.
제가 의도한 동작은 저 시점에서 solution 함수가 false를 반환하고 종료하는 것이었습니다. 하지만 실제로 디버깅을 통해 확인해보니, forEach문을 순회하다 저 시점에서 return문을 만남에도 불구하고 코드는 계속 forEach를 순회하였고, 결국 아래의 return true;까지 내려와 true를 반환하였습니다. 이로 인해 특정 케이스("))"와 같이 닫는 괄호로만 구성된 문자열)에서 계속 통과하지 못하고 있던 것이었습니다.
이 문제를 해결하려면, 그저 forEach문 대신 for문을 써주면 됩니다.
Stack Overflow를 확인해보니, 자바스크립트에서 반복문을 사용할 때 중간에 흐름을 중단하는 로직을 작성하려 한다면, forEach문은 적절한 도구가 아니라고 합니다.
위의 코드를 수정한 코드는 다음과 같습니다.
function solution(s){
s_arr = [...s];
stack = [];
for (i=0; i<s_arr.length; i++) {
item = s_arr[i];
if(item === "(") {
// push
stack.push(item);
} else {
// pop
if (stack.length == 0)
return false;
stack.pop();
}
}
if (stack.length !== 0) {
return false;
}
return true;
}
- 정리 : 자바스크립트에서 forEach문 내에 return이나 break를 사용해도 코드가 반복을 멈추지 않는다. 이럴때는 for문이나 다른 메소드를 사용하자.
'◼ FrontEnd > JavaScript' 카테고리의 다른 글
[JavaScript] 자바스크립트는 일급 함수를 지원하는 언어이다 (0) | 2024.09.03 |
---|