코딩 테스트/Programmers - 1

[JS] 핸드폰 번호 가리기

hayeonn 2022. 9. 22. 00:55
반응형

 

[풀이]

function solution(phone_number) {
    const numArr = phone_number.split("");
    const backNumber = numArr.splice(phone_number.length-4, 4).join("");
    const frontNumber = numArr.join("").replace(/[0-9]/g, "*");
    
    return frontNumber + backNumber;
}

1. 먼저 번호를 배열로 바꿔준다.

2. 뒤 4자리를 splice()를 통해 값을 받아 놓는다.

- 이때 splice(phone_number.length-4, 4) 인 이유

만약 phone_number가 "02777888" 이라면
numArr = ['0', '2', '7', '7', '7', '8', '8', '8']
phone_number.length = 8
phone_number.length - 4 = 4 이므로
splice(phone_number.length - 4, 4) = splice(4, 4) 가 된다.
결과적으로 뒤 4자리가 남게 된다.

3. join("")을 하면 backNumber은 "7888" 이 되고

4. frontNumber 은 replace(/[0 - 9]/g, "*"] 를 통해 앞자리 네개가 "****"로 바뀔 것이다.

5. 따라서 합치면 "****7888"이 나온다.

 
[코드 리뷰]
function solution(phone_number) {
  const numArr = phone_number.split("");
  const backNumber = numArr.splice(phone_number.length - 4, 4).join("");
  const frontNumber = numArr.map(el => "*").join("");
  return frontNumber + backNumber;
}

replace()를 이용하지 않고 map()함수를 이용해 풀어도 결과값이 같게 나온다.

const frontNumber = numArr.map(el => "*"); //['*', '*', '*', '*']

 

[추가 풀이]

1. reduce 풀이

function solution(phone_number) {
  return phone_number.split("").reduce((acc, cur, idx) => {
    return idx < phone_number.length - 4 ? (acc += "*") : (acc += cur);
  }, "");
}
phone_number.split("") ---> ['0', '2', '7', '7', '7', '8', '8', '8'] 이고
reduce()를 했을 때,
idx(인덱스값) < phone_number.length - 4 (= 4) 는 결국, 인덱스값 < 4 일 때 를 의미

인덱스값 < 4 일 때 ? (누적값 += '*') : (누적값 += 현재값) 


따라서, 인덱스값이 4보다 작은 '0', '2', '7', '7' 은 '*'로 누적되고
인덱스값이 4보다 '7', '8', '8', '8' 은 현재 숫자로 누적된다.

초기값이 '' (문자열)이기 때문에 ''안에 위 모든 값을 누적해 넣어준다.
'****7888' 이 리턴된다.

 

2. 명령형 접근 풀이 (for...in)

메서드 체이닝을 사용할 때보다 for...in 문을 활용해 시간복잡도 상 훨씬 효율적이다.

function solution(phone_number) {
  let result = "";

  for (const idx in phone_number) {
    if (idx < phone_number.length - 4) {
      result += "*";
    } else {
      result += phone_number[idx];
    }
  }
  return result;
}

for...in 은 인덱스값을 받아온다.

따라서 phone_number의 인덱스값을 가지고 판단한다.

만약 인덱스값이 4보다 작으면 결과값(문자형) 안에 "*" 를 누적시켜 더해주고

4보다 크면 그에 맞는 phone_number의 인덱스값을 누적해 더해준다.

 

3. Array생성자 + fill() + substring

function solution(phone_number) {
  const starQuantity = phone_number.length - 4;

  return (
    new Array(starQuantity).fill("*").join("") +
    phone_number.substring(starQuantity)
  );
}
phone_number = "02777888"
starQuantity = 4
new Array(starQuantity).fill("*").join("") = "****"

이때 new Array 는 새로운 배열을 생성해준다.
new Array() 는 빈 배열을 의미하며 []
new Array(4) 는 빈 배열 안에 4가지의 값을 넣을 수 있는 공간을 만들어준다. [ empty * 4]
new Array(4).fill("*") 는 ["*", "*", "*", "*"] 이고
new Array(4).fill("*").join("")을 하면 "****" 이 된다.

substring(start) 을 넣으면 인덱스 start 부터 last 까지 값을 리턴해준다.
따라서, phone_number.substring(4) 는 "7888"이 된다.

 

4. 한줄코드 (repreat 이용)

function solution(phone_number) {
  return "*".repeat(phone_number.length - 4) + phone_number.slice(-4);
}
phone_number = "02777888"

"*".repeat(4) = "****"
phone_number.slice(-4) = "7888"

slice(start, last)는 두 개의 파라미터값을 받는데, 두번째 파라미터 값을 받지 않으면
slice(start) => start 인덱스부터 마지막 인덱스까지 모두 잘라낸다.
그리고 값이 음수(-N)일 경우 = 뒤에서 부터 N 번째 라는 뜻이다.

따라서, slice(-4)이면 뒤에서부터 4번째 부터 잘라주면 된다. 

헷갈린다면 예시)
numbers = [1, 2, 3, 4, 5] 일 때
numbers.slice(-4) 은 numbers.slice(1) 의 값과 같다고 볼 수 있다.
뒤에서 4번째 값은 2 이고 2의 인덱스값은 1 이므로 결과값은 [2, 3, 4, 5]

 

 

[출처 - slice]

https://bigtop.tistory.com/55

 

[JavaScript] 자바스크립트 slice 메서드 이해하기

slice 메서드란? slice 메서드는 배열의 일부 요소를 제거한 새로운 배열을 반환한다. 그래서 slice 메서드는 splice 메서드와 다르게 원래의(기존의) 배열 값을 수정하지 않는다. 다른 면에서 생각하

bigtop.tistory.com