이번 글에서는 두 개의 문자열을 입력받아, 첫 번째 문자열이 두 번째 문자열 안에 몇 번 등장하는지 그 횟수를 반환하는 JavaScript 함수를 작성해 보겠습니다.
예를 들어, 다음과 같은 메인 문자열이 있다고 가정해 봅시다.
const main = 'This is the is main is string';
우리가 찾아야 할 대상 문자열은 다음과 같습니다.
const sub = 'is';
위 예제에서 'is'라는 문자열은 메인 문자열 안에 총 4번 등장합니다. 이제 이 기능을 수행하는 함수의 코드를 작성해 보겠습니다.
구현 예제
가장 간단하고 효율적인 방법은 정규표현식(RegExp)에 전역 검색 플래그 g를 적용한 뒤, replace() 메서드를 활용하여 매칭되는 횟수를 세는 것입니다.
const main = 'This is the is main is string';
const sub = 'is';
const countAppearances = (main, sub) => {
const regex = new RegExp(sub, "g");
let count = 0;
main.replace(regex, () => {
count++;
});
return count;
};
console.log(countAppearances(main, sub));실행 결과
위 코드를 실행하면 콘솔에 다음과 같은 결과가 출력됩니다.
4
코드 설명
동작 원리를 단계별로 살펴보면 다음과 같습니다.
1. 정규표현식 생성: new RegExp(sub, "g")를 통해 찾고자 하는 문자열을 패턴으로 하는 정규표현식 객체를 만듭니다. 여기서 "g"(global) 플래그는 문자열 전체에서 일치하는 모든 부분을 찾도록 지정합니다. 이 플래그가 없으면 첫 번째 일치 항목만 찾고 멈추게 됩니다.
2. replace()로 카운팅: replace() 메서드는 사실 원본 문자열을 변경하지 않으면서, 일치할 때마다 콜백 함수를 호출합니다. 이 콜백 함수 안에서 카운터 변수를 증가시키면 일치 횟수를 셀 수 있습니다.
3. 결과 반환: 최종적으로 누적된 count 값을 반환합니다.
split()을 활용한 대안 방법
정규표현식 없이 더 간결하게 작성하고 싶다면 split() 메서드를 활용할 수도 있습니다.
const countAppearances = (main, sub) => {
return main.split(sub).length - 1;
};
console.log(countAppearances(main, sub)); // 4이 방법은 대상 문자열을 구분자로 삼아 메인 문자열을 나누면, 조각의 개수보다 항상 하나 적은 수만큼 해당 문자열이 등장한다는 원리를 이용합니다. 코드가 짧아 가독성이 좋다는 장점이 있습니다.
주의사항: 겹치는 경우(Overlapping)
위 두 방법 모두 겹치는(overlapping) 매칭은 별도로 계산하지 않습니다. 예를 들어 'aaa'에서 'aa'를 찾으면 겹치지 않는 매칭은 1번으로 계산됩니다. 겹치는 경우까지 모두 세려면 인덱스를 한 칸씩 이동하며 직접 탐색하는 로직이 필요합니다.
const countOverlapping = (main, sub) => {
let count = 0;
let pos = main.indexOf(sub);
while (pos !== -1) {
count++;
pos = main.indexOf(sub, pos + 1);
}
return count;
};
console.log(countOverlapping('aaa', 'aa')); // 2상황에 맞는 방법을 선택하면 됩니다. 일반적인 용도라면 정규표현식 방식이나 split() 방식이 충분히 실용적입니다.