JavaScript/알고리즘

프로그래머스 배열 만들기 2 JS ( /^[패턴]+$/, 정규식으로 숫자를 찾으려면 String으로 타입변환 )

hihiha2 2023. 6. 16. 02:51
반응형

문제 설명

정수 l과 r이 주어졌을 때, l 이상 r이하의 정수 중에서 숫자 "0"과 "5"로만 이루어진 모든 정수를 오름차순으로 저장한 배열을 return 하는 solution 함수를 완성해 주세요. 만약 그러한 정수가 없다면, -1이 담긴 배열을 return 합니다.

 

 

 

🙋‍♀️ 내 생각

0과 5로만 이루어진 정수를 어떻게 찾을것인가가 이 문제의 핵심이라고 생각했다.

5와 0이 들어가더라도 그 외의 값을 포함하고 있으면 안되기 때문에 그것을 어떤식으로 검사할 것인지가 중요한 것같다.

나는 정규식을 이용해서 찾을값을 지정하여 문제를 해결했다.

 

 

 

 

✅ 내 코드

function solution(l, r) {
  const result = [];

  for (let i = l; i <= r; i++) {
    if (/^[05]+$/.test(i)) {
      result.push(i);
    }
  }

  return result.length === 0 ? [-1] : result;
}

우선, 해당하는 값만을 담을 배열을 result라는 이름으로 만들어주었다.

 

다음으로, l이상 r이하의 정수라는 조건이 있기때문에 for문을 통해서 범위를 지정해주었다.

i의 시작값을 l,마지막값이 r이고 1씩 더하기 때문에 l과 r사이의 모든 정수를 검사할 수 있다.

여기까지의 값을 push()해서 확인해보면 아래와 같이 범위의 모든 값이 배열에 담긴것이 보인다.

 

그런 다음, if문을 통해서 값을 검사한다.

5와 0만으로 이루어진 값을 찾기 위해서 정규식을 이용하였다.

 

/^[05]+$/

문자열의 시작(^)부터 끝($)까지 검사하여 "0" 또는 "5"가 하나 이상(+) 연속되는지를 확인

전체 문자열이 "0" 또는 "5"로만 이루어져 있어야 일치

 

if문의 ()안에는 Boolean값이 들어가야 하기때문에 정규식의 .test()를 이용하여 해당값이 true인지, false인지를 구한다.

만약, true라면 result에 값을 push()한다.

 

 

 

 

 

💻  학습한 것

특정문자가 포함됐는지 알고 싶을때정규식을 구하는 방법을 공부했다.

 

/05/ : "05"라는 연속된 문자열을 찾는다. (정확하게 "05"인 문자열 - 순서상관O)

/[05]/: "0" 또는 "5"가 나오는 경우를 모두 찾는다 (0 또는 5를 독립적으로 취급 - 순서상관X)

/^[05]/: 문자열의 시작 부분에 "0" 또는 "5"가 있는 경우 (0 또는 5를 독립적으로 취급 - 순서상관X)

/^[05]$/: 문자열의 전체가 단일한 "0"또는 "5"로 이루어진 경우 (문자열의 길이가 1, 값이 0 또는 5인경우)

/^[05]+$/: 문자열의 전체가 "0"또는 "5"로 이루어진 경우 (문자열의 길이1이어도 되고 더 길어도 됨)

 

 

모두 비슷한 형태라서 공부하고 완전히 이해하는데 시간이 좀 걸렸다. 해당문제에 계속 이렇게 저렇게 바꾼 값을 넣으며 이해하기 위해 노력했다. 그래도 정확하게 알고 넘어가야 다음에는 더 잘 활용할 수 있을것이라고 생각한다.

 

특히 어려웠던 부분은 +에 대한 해석이었다. 그러다가 +를 붙이지 않으면, 문자열의 길이가 1이고 정확하게 그 값이 일치해야 한다는 것을 알게되어 이해했다.

 

예를 들어 01을 넣어서 테스트를 해보았다.

우선 /^[01]+$/ 과 같이 +를 포함하여 실행하면 결과값이 아래와 같이 나온다.

1 또는 0을 포함하고 있는 값은 길이에 상관없이 모두 찾는다.

 

다음으로 /^[01]$/ 를 보자.

결과값을 보면 [] 빈배열이 나온다. 

왜냐하면 +를 포함하지 않으면, 문자열의 길이가 1인 값을 찾기 때문이다.

단일한 "0"또는 "1"을 찾는것이다. 

위의 조건이 5부터 시작이므로 0과 1은 포함되지 않아서 빈배열이 나온다.

 

🔫 /^[05]+$/  과 /^[05]$/ 를 쉽게 이해하기

/^[05]$/는 문자열의 길이가 1이고 완전히 단일한값을 찾는다!!

 

 

 

❌ 보완할 점

위의 코드로 실행해도 결과값이 잘나온다. 하지만 위의 코드에서는 문제점이 하나있다. 

바로 묵시적 타입변환이다. 

 

문제를 다 풀고 다른 사람들의 코드를 보면서 알게된 문제점이었다. 

다른 사람들의 코드를 보니, i를 string으로 타입을 변환해주는 처리를 많이 해주었길래 찾아봤다.

 

정규식은 일반적으로 문자열에서 작동하며 특정한 문자열 패턴을 찾을때 사용된다.

만약 찾고자 하는 특정한 값이 숫자라면, 숫자를 문자열로 형변환을 한 뒤 정규식을 적용해야한다.

 

위의 코드로 예를 들면 내가 찾고자하는 값은 0또는 5의 값인데, 정규식은 이 값들 문자열패턴으로 인식한다.

그래서 패턴을 통해 찾고자 하는 값(i)이 문자열이라면 상관없지만, 만약 숫자라면 숫자를 String으로 형변환을 해야한다.

 

위의 코드에서 문제가 발생하지 않았던 이유는 i변수는 숫자이지만 if (/^[05]+$/.test(i))  이렇게 정규식검사를 수행하면서 묵시적으로 문자열로 변환되기 때문이다. 



🤔 묵시적 타입변환의 문제점

묵시적 타입변환은 타입이 추론되어 묵시적으로 변경되는 것을 의미한다. 자바스크립트는 일일이 타입을 지정해주지 않기때문에 이렇게 묵시적으로 변환되기도 한다.

코드를 짤때는 편하지만, 짜는 사람도 타입이 변환된 것을 인지하지 못하기때문에 추후에 문제가 발생할 수 있다 (예측가능성이 떨어진다)

➡️ 코드의 가독성 ⬇️, 예측가능성 ⬇️

 

 

 

✅ 보완한 코드

// 방법1 
function solution(l, r) {
    const result = []
    
    for(let i=l; i<=r; i++ ){
      if(/^[05]+$/.test(String(i))){
        result.push(i)
       } 
    }
    
    return result.length === 0? [-1] : result
}

test메서드 안에서 String()을 통해서 타입변환을 해준다.

 

 

// 방법2
function solution(l, r) {
    const result = []
    
    for(let i=l; i<=r; i++ ){
      const strNum = String(i)
      if((/^[05]+$/).test(strNum)){
        result.push(i)
       } 
    }
    
    return result.length === 0? [-1] : result
}

변수를 따로 선언하고 형변환을 해준다음에 test()에 넣는다.

 

 

사실상 같은 코드인데, 변수로 따로 사용했는지 아닌지만 다르다. 

 

 

🙋‍♀️ 내 생각

문제자체를 푸는데 걸린 시간보다 풀고나서 관련된 것들을 공부하는데 시간이 훨씬 많이 걸렸다.

 

우선 이 문제를 풀면서 가장 새롭게 알게 된것은 정규식은 특정한 문자열 패턴을 찾는데 이용하기 때문에, 숫자를 찾고자한다면 타입변환을 해주어야 묵시적 타입변환을 피할 수 있다는 것이다.

 

또한 정규식의 조건을 세우는 다양한 방법들도 깊이있게 공부했다. 정말로 한끗차이인데 그 값의 결과값은 달라서 디테일한 것들을 정확하게 이해하고 넘어가야겠다고 생각했다. 

 

문제로는 한문제이지만 많은 것들을 배울 수 있는 문제였다.

 

반응형