백준 문제를 풀던 중 replace() 메서드를 쓰면 풀리지 않고 replaceAll() 메서드로 수정했을 때 풀리는 문제가 있어 둘의 차이를 이해하고 왜 문제에서 오답처리가 되었는지 알아보고자 한다.
https://www.acmicpc.net/problem/2941
문제는 다음과 같이 입력으로 주어진 단어를 분석하여 알파벳의 길이를 출력하면 되는 문제다.
// 2941 크로아티아 알파벳
let fs = require('fs');
let input = fs.readFileSync('index.txt').toString().trim().split('\n');
let arr = input[0]
let cro = ["c=", "c-", "dz=", "d-", "lj", "nj", "s=", "z="]
for (let i = 0; i <cro.length; i++){
arr = arr.replaceAll(cro[i], "/") // replaceAll 대신 replace 사용 시 오답
}
console.log(arr.length)
console.log(arr)
그런데 여기서 replaceAll 메서드 대신 replace 메서드를 사용 시 오답처리 된다. 처음에는 이해가 안 갔지만 찾아보니 너무 당연한 오답이었다.
replace() 메서드는 해당 문자열을 한 번만 찾아 변경하고 replaceAll()은 해당하는 문자열을 모두 찾아 치환한다.
다른 언어에 반해 자바스크립트는 replace first 방식을 선택하여 replace() 메서드를 사용 시 첫 번째 치환 대상을 발견 시 한 번만 치환하고 메서드를 종료한다.
let str = 'ab?c?'
str = str.replace("?", "@") // ab@c?
ECMA-262 12th(2021) 스펙을 기준으로 replaceAll() 기능이 추가되어 최신 자바스크립트 엔진에서는 replaceAll() 메서드를 사용할 수 있다. replaceAll() 메서드는 변환 대상을 모두 찾아 치환한다.
let str = 'ab?c?'
str = str.replaceAll("?", "@") // ab@c@
replace() 메서드의 첫 번째 매개변수로 정규표현식을 사용할 수 있는데 이를 통해 replaceAll() 메서드처럼 사용이 가능하다.
let str = 'ab?c?'
str = str.replace(/\?/g, "@") // ab@c@
위 코드처럼 첫 번째 매개변수에 정규표현식을 사용하면 replaceAll() 메서드처럼 사용할 수 있다. 정규표현식을 해석하면 // 안에 있는 "?"("?"를 찾고 싶은데 그냥 ?(물음표)나 "(따옴표)등을 문자열 취급하기 위해 앞에 \기호를 붙여준다)를 전역에서 찾는다는 뜻이다. 정규표현식 예제는 아래있다.
너무 좋은 글이네요. 공유해주셔서 감사합니다.