상현에 하루하루
All 개발자의 하루

글자 중복 계산

( 업데이트: )

입력 문자열에 대해서 대소문자를 구분하지 않는 영문자와 숫자의 개수를 반환하는 함수를 작성하십시오. 입력 문자열은 알파벳(대문자 및 소문자)과 숫자 만 포함한다고 가정 할 수 있습니다.

ex)

  • “abcde” -> 0 `# no characters repeats more than once`
  • “aabbcde” -> 2 `# ‘a’ and ‘b’`
  • “aabBcde” -> 2 `# ‘a’ occurs twice and ‘b’ twice (‘b’ and ‘B’)`
  • “indivisibility” -> 1 `# ‘i’ occurs six times`
  • “Indivisibilities” -> 2 `# ‘i’ occurs seven times and ‘s’ occurs twice`
  • “aA11” -> 2 `# ‘a’ and ‘1’`
  • “ABBA” -> 2 `# ‘A’ and ‘B’ each occur twice`

function duplicateCount(text){
  text = text.toLowerCase();

  const middleResult = text.split('').reduce((acc, cur) => {
    if (acc[cur]) acc[cur]++;
    else acc[cur] = 1;
    return acc;
  }, {});
  let sortable = [];
  for (let i in middleResult) {
    sortable.push([i, middleResult[i]]);
  }
  sortable = sortable.filter(a => a[1] > 1);

  return sortable.length;
}

위 처럼 구성한 의도는

  1. 대소문자를 구분하지 않는다는 점에서 String.prototype.toLowerCase()를 통해서 모두 소문자로 변경하였다.
  2. 객체로 각각의 글자에 대해서 몇개씩 가지고있는지 카운팅하는 reduce를 만들었다.
  3. 배열로 변경해서 제일 많이있는 순서대로 정렬하고 제일 많은 것을 반환하는 줄알았는데 아니어서 필터로 2개이상 가지고있는 요소만 남겼다.
  4. 배열의 갯수를 return

일단 문제를 해결하긴했다. 하지만 Best 해결법을 보니 좀더 간단하게 풀수 있던거같다.

function duplicateCount(text){
  return (text.toLowerCase().split('').sort().join('').match(/([^])\1+/g) || []).length;
}

join까지는 비슷한 방식으로 생각해낼수있고 match에서 정규식을 통해서 ([^])\1 1번그룹과 동일한 글자가 나오는 것을 찾는다. 위 방식대로 하고 return 값이 없다면 빈 배열을 반환해서..

깔끔하고 좋은 것같다.