자료구조와 자료형 : 문자열

라용·2022년 11월 21일
0

모던 JavaScript 튜토리얼 내용 일부를 정리 요약한 내용입니다. 더 자세한 설명은 원문 링크를 참고하세요.

생각

코드카타를 하면 써봤던 메소드들도 있고, 아에 생소한 것들도 있다. 이게 뭐지 싶은 것들은 당장 쓸 일이 없을 것 같아 따로 적지 않았다. 검색관련 개발을 하면, 이런 문자 관리가 중요하지 않을까 싶다. 아직은 아니다.


정리

자바스크립트는 글자 하나만 저장하는 별도 자료형이 없고, 텍스트 형식 데이터는 길이에 상관없이 모두 문자열 형태로 저장됩니다. (인코딩 방식과 상관없이 항상 UTF-16 형식을 따름)

백틱

백틱을 사용하면 표현식을 ${...} 로 감사 문자열 사이에 넣어줄 수 있고, 문자열을 여러 줄에 걸쳐 작성할 수 있습니다. 이를 템플릿 리터럴이라고 합니다.

function sum(a, b) {
    return a + b;
}

alert(`1+2 = ${sum(1, 2)}.`); // 1 + 2 = 3.

특수기호

줄 바꿈 문자인 특수기호 \n 을 사용하면 작은따옴표나 큰따옴표로도 여러 문자열을 만들 수 있습니다. 이외에 다양한 특수 문자 있으며 모두 이스케이프 문자, 역슬레시로 시작합니다. (추가 내용은 원문 링크 참고)

let str1 = "Hello \n World";

let str2 = `Hello
World`;

str1 == str2; // true

특정 글자 접근

문자열 내 특정 위치에 접근하려면 대괄호 혹은 str.charAt() 을 사용합니다. 최근에는 대괄호를 많이 사용하며 접근하려는 위치에 글자가 없을 경우 대괄호는 undefined 를 charAt 은 빈 문자열을 반환합니다.

let str = `Hello`

str[0]; // H
str[1000] // undefined

str.charAt(0); // H
str.charAt(1000); // ''

// 마지막 글자는 전체 길이에서 1을 뺌, 인덱스가 0부터 시작하므로
str[str.length - 1]; // o

for .. of 를 사용하면 문자열의 글자를 순차적으로 순회할 수 있습니다.

for (let char of "Hello") {
	alert(char); // H, e, l, l, o 
}

대소문자 변경

toLowerCase() 와 toUpperCase() 를 사용하면 대소문자 변경이 가능합니다. 글자 하나만 지정해서 변경할 수도 있습니다.

'Interface'.toUpperCase(); // INTERFACE
'Interface'.toLowerCase(); // interface

'Interface'[0].toLowerCase(); // 'i'

부분 문자열 찾기

str.indexOf(substr, pos) 메서드를 사용하면 문자열 str 에서 substr 의 위치를 찾아줍니다. pos 넣으면 해당 위치부터 검색을 시작합니다. 해당 문자열이 없다면 -1을 반환합니다.

let str = "Widjet with id";

str.indexOf('widget'); // 0
str.indexOf('widget'); // -1, 대소문자 구분하므로 찾지 못함
str.indexOf('id'); // 1
str.indexOf('id', 2); // 12

문자열 내 부분 문자열 전체 대상으로 무언가 하고 싶다면 반복문 안에 indexOf를 사용합니다. 반복문이 돌 때마다 검색 시작 위치가 갱신되면서 indexOf 가 새롭게 호출됩니다. (전체 문자열에 담긴 해당 문자를 찾고 싶다면 이런 방식 사용)

let str = 'As sly as a fox, as strong as an ox'
let target = 'as'; // 찾을 것
let pos = 0; // indexOf 의 두번째 인자, 검색 시작 위치

while (true) {
    let foundPos = str.indexOf(target, pos);
    if (foundPos == -1) break;

    alert(`위치: ${foundPos}`)
    pos = foundPos + 1; // 찾은 것 기준으로 다음 위치를 확인해 검색 이어감
}

코드를 짧게 줄이면, (while 조건부 쪽이 약간 이해가 안됨)

let pos = -1;
while((pos = str.indexOf(target, pos + 1)) != -1){
    alert(`위치 : ${pos}`)
}

if 문의 조건식으로 indexOf 를 사용한다면, 해당 값이 -1 이 아닐 때를 찾으면 됩니다.

let str = "Widget with id";

if (str.indexOf("Widget") != -1) {
    alert("찾았다"); 
}

비트 NOT 연산자 ~ 를 사용하면 위 식을 더 간결하게 바꿀 수 있습니다. n 이 32비트 정수일 때 ~n 은 -(n+1) 입니다. 그래서 ~n 중 0을 만드는 경우는 n 이 -1인 경우가 유일하므로 아래처럼 조건을 적용할 수 있습니다. 직관적이지 않아 추천하지 않지만 레거시 코드에서 발견할 수 있으니 부분 문자열인지 확인하는 코드라고 알아둡니다.

let str = "Widget with id";

if (~str.indexOf("Widget")) { // -1 이 아니면 동작하는
    alert("찾았다"); 
}

includes, startsWith, endsWith

str.includes(substr, pos) 는 str 에 substr 이 있는지에 따라 true 나 false 를 반환합니다. 부분 문자열의 포함 여부만 확인하기 좋습니다. 두번재 인수를 넘기면 해당 위치부터 부분 문자열을 검색합니다. startsWith 와 endsWith 는 str 이 특정 문자열로 시작하는지, 끝나는지 여부를 확인해 줍니다.

'Widget'.includes('Widget'); // true
'Hello'.includes('Bye'); // false

'Widget'.startsWith('Wid'); // true
'Widget'.endsWith('get'); // true

부분 문자열 추출

str.slice(start [, end]) 는 문자열의 start 부터 end 앞 까지 문자열을 반환합니다. 두번째 인수가 생략되면 시작점부터 끝까지 문자열을 반환하고 음수를 기준으로 하면 문자열 끝에서부터 카운팅을 합니다.

let str = 'stringify';

str.slice(0, 2); // 'st' 반환
str.slice(2); // 'ringify' 반환
str.slice(-4, -1) // 'gif'

str.substring(start [, end]) 는 start 와 end 사이에 있는 문자열을 반환합니다. slice 와 유사하지만 start 보다 end 가 커도 같게 동작하는 차이가 있습니다.

let str = "stringify"

str.substring(2, 6); // 'ring'
str.substring(6, 2); // 'ring'

str.substr(start [, length])는 start 부터 시작해 length 개의 극자를 반환합니다. 첫 번째 인수가 음수면 뒤에서 부터 개수를 셉니다.

let str = "stringify";

str.substr(2, 4); // 'ring'
str.substr(-4, 2); // 'gi'

문자열 추출 메서드는 slice 만 알아두고 사용해도 좋습니다.

문자열 비교

문자열은 알파벳 순서를 기준으로 비교가 이루어지는데 소문자가 대문자보다 크고 발음 구별 기호가 붙은 문자는 알파벳 순서를 따르지 않습니다. 모든 문자열은 UTF-16 을 사용해 인코딩하는데 UTF-16은 모든 글자가 숫자 형식의 코드와 매칭됩니다.

str.codePointAt(pos) 를 사용하면 pos 에 위치한 글자의 코드를 반환합니다. 반대로 String.fromCodePoint(code) 는 숫자 형식의 code 에 대응하는 글자를 만듭니다.

'z'.codePointAt(0); // 122
'Z'.codePointAt(0); // 90

String.fromCodePoint(90); // Z

문자열 제대로 비교

언어마다 문자 체계가 달라 문자열을 제대로 비교하기는 쉽지 않습니다. 그래도 모던 브라우저에서는 국제화 관련 표준인 ECMA-402 를 지원하므로 str.localeCompare(str2) 메서드를 사용할 수 있습니다.

str.localeCompare(str2)

// str < str2  - 음수 반환
// str > str2  - 양수 반환
// str = str2  - 0 반환

이 외에 str.trim() 을 사용하면 문자열 앞과 끝의 공백을 제거해주고, str.repeat(n) 을 사용하면 문자열을 n 번 반복합니다.

profile
Today I Learned

0개의 댓글