문자열과 문자 String & Character

Ios_Roy·2023년 3월 5일
0

swift 문법

목록 보기
23/29
post-thumbnail

아스키코드와 유니코드

  • 유니코드(Unicode)는 전 세계의 모든 문자를 컴퓨터에서 일관되게 표현하고 다룰 수 있도록 설계된 산업 표준
  • 스위프트는 유니코드의 체계를 사용

유니코드와 문자열의 저장

  • 스위프트의 문자열(String)?
  • 쌍따옴표 안에 문자(Character)들을 연결
  • 모든 문자열은 개별 인코딩된 유니코드 문자들(encoding-independent Unicode characters)로 구성
  • 유니코드 값(코드포인트 - 스칼라값)
  • 결국, 스위프트는 문자열을 저장할때, 하나의 문자를 유니코드의 스칼라값(UTF-32)으로 저장
  • 그리고 언제든지 UTF-8, UTF-16방식으로도 쉽게 변환할 수 있는 방법도 제공해줌
  1. 문자열.unicodeScalars
  2. 문자열.utf8
  3. 문자열.utf16
var someString: String = "Some Swift😃"

// 문자열은 결국, 각 문자를 모아놓은 데이터 바구니

for code in someString.unicodeScalars {
    print(code.value)
}

/**=====================================
 - 문자열    UTF-32값         (16진법 표현)
 - "S"     -   83   ====>    53 (16진법)
 - "o"     -  111   ====>    6F (16진법)
 - "m"     -  109   ====>    6D (16진법)
 - "e"     -  101   ====>    65 (16진법)
 - " "     -   32   ====>    20 (16진법)
 - "S"     -   83   ====>    53 (16진법)
 - "w"     -  119   ====>    77 (16진법)
 - "i"     -  105   ====>    69 (16진법)
 - "f"     -  102   ====>    66 (16진법)
 - "t"     -  116   ====>    74 (16진법)
 - "😃"    -128515  ====> 1F603 (16진법)

Swift공식문서로 살펴보는 유니코드 예시

  • 스위프트는 내부적으로 문자열을 UTF-32방식으로 저장하고 있지만
    나머지, UTF-8, UTF-16방식으로도 쉽게 변환할 수 있는 방법도 제공해줌
    (코드값을 사용하려면 물론, for문을 통해서 내부에서 요소를 다시 추출해서 사용해야함)
let dogString = "Dog‼🐶"
print(dogString.utf8)

for codeUnit in dogString.utf8 {             //  8비트의 숫자값
    print("\(codeUnit) ", terminator: "")
}
print("")

// 68  / 111  / 103 / 226 128 188 / 240 159 144 182

for codeUnit in dogString.utf16 {            // 16비트의 숫자값
    print("\(codeUnit) ", terminator: "")
}
print("")

// 68 / 111 / 103 / 8252 / 55357 56374

for scalar in dogString.unicodeScalars {      // 32비트의 숫자값
    print("\(scalar.value) ", terminator: "")
}
print("")

// 68 / 111 / 103 / 8252 / 128054

유니코드로 인한 스위프트 문자열의 특징과 주의점

var hangul1 = "\u{D55C}"     // "한"

print("\"한\"의 글자수: ", hangul1.count)

var hangul2 = "\u{1112}\u{1161}\u{11AB}"      // "ㅎ" "ㅏ" "ㄴ"
print("\"ㅎ\"+\"ㅏ\"+\"ㄴ\"의 글자수: ", hangul2.count)

hangul1 == hangul2

// 한글과 같은 언어들을 "ㅎ" "ㅏ" "ㄴ" 내부적으로 하나의 글자로 취급 ⭐️

var word = "cafe"
print("글자의 숫자 \(word) is \(word.count)")
// "글자의 숫자 cafe is 4"

word += "\u{301}"    // COMBINING ACUTE ACCENT, U+0301

print("글자의 숫자 \(word) is \(word.count)")
// "글자의 숫자 café is 4"

스위프트의 문자열에서는 배열같은 단순 인덱스(index) 접근이 불가능 ⭐️

  • 스위프트는 문자열을 글자의 의미단위로 사용하기 때문에, 정수 인덱스 사용이 불가능
  • 0, 1, 2, 3, 4 ....   (X)

스위프트의 문자열 String / NSString

  • 스위프트에서는 2개의 문자열 자료형을 사용
  • 문자열 내부적으로 서로 연동(bridged)
  • String ▶︎ Swift String  구조체/값형식 (스위프트 문자열)
  • NSString ▶︎ Foundation String  클래스/참조형식  (파운데이션 문자열)
) NSString ▶︎ Foundation String  클래스/참조형식  (파운데이션 문자열)
==================================================================**/

var nsString: NSString = "Swift"   // 문제없이 저장

//let string: String = nsString   //에러발생
let string: String = nsString as String

// String <===> NSString간에 자동으로 변환컨버팅되지는 않음(타입캐스팅해야함)

nsString.length       // NSString의 length속성 ===> 유니코드수(UTF-16) 기반
string.count          // String의    count속성 ===> 의미 글자수 기반

nsString = string as NSString    // 두형식은 브릿징이 가능한 타입 (Toll-Free Bidged) ===> 타입캐스팅으로 호환되는 자료형

// 두 자료형은 서로 호환되는 자료형이지만, 유니코드를 처리하는 방식이 달라서, 조심해서 사용해야함 ⭐️

// word = café 라는 단어가 저장되어 있음

let nsWord = word as NSString

word.count
nsWord.length

// NSString은 Objected-C에서 사용하는 문자열이고
// NSString에서 더 파생된 개념인 NSAttributedString을 실제 앱을 만들때, 간혹가다 사용하는 경우가 있음
// 문자열에 클릭기능을 넣는다던지. 글자별로 색깔을 다르게 한다던지

멀티라인 스트링 리터럴(Multiline String Literals)

  • 문자열을 한줄에 입력 ➞ 명시적인 줄바꿈이 불가능
  • 문자열을 여러줄 입력하고 싶을때
  • """ (쌍따옴표 3개를 연속으로 붙여서 입력) - 첫째줄/마지막줄에 입력
  • 해당줄에는 문자열 입력 불가
  • 문자열 내부에서 쓰여진대로 줄바꿈됨. ===> (줄바꿈 하지 않으려면 (백슬레시) 입력)
  • 특수문자는 문자 그대로 입력됨
  • 마지막(""")는 들여쓰기의 기준의 역할
let singleLineString = "These are \nthe same."       // 줄바꿈을 원하면, \n 입력   \ (Escape character)
print(singleLineString)
let quotation = """
The White Rabbit put on his spectacles.  "Where shall I begin,
please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on
till you come to the end; then stop."
"""
print(quotation)

문자열 내에서 특수문자 (Escape sequences)

  • \0 (null문자)
  • \ (백슬레시)
  • \t (탭)
  • \n (줄바꿈 - 개행문자)
  • \r (캐리지 리턴 - 앞줄이동)
  • \" (쌍따옴표)
  • \' (작은따옴표)
  • \u{유니코드값} (1~8자리의 16진수)
let wiseWords = "\"Imagination is more important than knowledge\" - Einstein"
print(wiseWords)

로스트링(Raw String) - 확장 구분자(Extended String Delimiters)

  • 문자열내에서 특수문자를 많이 써야하는 상황이라면,
  • 글자 날것 그대로 표현하는 것이 코드에서 덜 헷갈릴 수 있음
  • 샵 기호(#)으로 문자열 앞뒤를 감싸면 내부의 문자열을 글자 그대로 인식
var name = #"Steve"#
print(name)

let string1 = #"Line 1\nLine 2"#       // 특수문자가 그대로 인식됨
print(string1)

let string2 = #"Line 1\#nLine 2"#
print(string2)

let string3 = ###"Line 1\###nLine 2"###
print(string3)

let string4 = #"My name is \#(name)"#         // 이스케이프 시퀀스 효과를 사용하려면, 샵을 입력

let threeMoreDoubleQuotationMarks = #"""
Here are three more double quotes: """
"""#

print(threeMoreDoubleQuotationMarks)

문자열 보간법(String Interpolation)

문자열 보간법의 동작원리

  • 문자열 내에서 "(표현식 등)"
  • 상수, 변수, 리터럴값, 그리고 표현식의 값을 표현가능
let name = "유나"
//print("브레이브걸스: \(name)")

let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
print(message)

문자열 보간법 사용시, 출력 형태(방법)을 직접 구현도 가능

[애플이 미리 만들어 놓은 프로토콜]
 - 아래의 프로토콜을 채택해서 구현하면 스트링 인터폴레이션을 직접구현 가능
 
   protocol CustomStringConvertible {
      var description { get }
   }
========================================================**/

//extension Dog: CustomStringConvertible {
//    var description: String {
//        return "강아지의 이름은 \(name)이고, 몸무게는 \(weight)kg 입니다."
//    }
//}

// 강아지의 이름은 초코이고, 몸무게는 15.0입니다.

서브 스트링(Substring)의 개념

  • prefix(...)메서드 등의 사용시
  • "Hello"란 beginning문자열은 greeting 문자열의 메모리공간을 공유
  • 스위프트 내부적으로 최적화되어 있음
  • 수정 등이 일어나기 전까지 메모리 공유
  • 오랜기간 저장하기 위해서는, 새롭게 문자열로 저장할 필요
var greeting = "Hello, world!"

let index: String.Index = greeting.firstIndex(of: ",") ?? greeting.endIndex    // ,(콤마)의 인덱스
let beginning: String.SubSequence = greeting[..<index]// 처음부터 인덱스까지

// "Hello"   // 타입 확인해보기 ⭐️  String.SubSequence 타입
var word: String.SubSequence = greeting.prefix(5)

word     // String.SubSequence 타입
// "Hello"

greeting = "Happy"    // 원본을 바꾸는 순간 Substring 문자열들은 새로운 문자열 공간을 만들어서 저장

print(beginning)
print(word)

word = greeting.suffix(3)

word     // String.SubSequence 타입
// "ppy"

// 아니면 명시적으로 문자열로 변환해서 저장 가능 (서브스트링에서 벗어남)
let newString: String = String(word)

문자열을 배열로 변환

  • 문자열의 배열화, (문자열)배열의 문자열화
  • 문자열 자체도, 여러개의 문자를 담고 있는 데이터이기 때문에
    쉽게 배열로 변형이 가능하고, 반대 변형도 쉬움
  • String <====> [String] 문자열 배열
  • String <====> [Character] 문자 배열
var someString = "Swift"

// 1) 문자열을 문자열(String) 배열화 하기 ⭐️

var array: [String] = someString.map { String($0) }
print(array)

// 2) 문자열을 문자(Character) 배열화 하기

var array2: [Character] = Array(someString)     // [Character]      //typealias Element = Character

// (참고) 문자열을 문자열(String) 배열화하는 추가적 방법
var array3: [String] = Array(arrayLiteral: someString)  // [String]

// 3) 문자열 배열 [String] =====> 문자열

var newString = array.joined()
newString = array3.joined()

// 4) 문자 배열  [Character] ======> 문자열

var newString2 = String(array2)
someString = "Swift"

someString.randomElement()     // 문자열에서 랜덤으로 뽑아내는 것 가능
someString.shuffled()          // 섞어서 문자(Character) 배열로 리턴 ["t", "i", "w", "S", "f"]

//someString.shuffled().joined()     // 불가능 (문자배열 이기때문)

var newString3 = String(someString.shuffled())
print(newString3)

// map고차함수를 사용해서 변환 ⭐️

newString3 = someString.map { String($0) }.shuffled().joined()
print(newString3)

문자열 다루기

  • 문자열의 대소문자 변형
var string = "swift"

string.lowercased()    // 전체 소문자로 바꾼 문자열 리턴 (원본 그대로)
string.uppercased()    // 전체 대문자로 바꾼 문자열 리턴 (원본 그대로)

string.capitalized     // 대문자로 시작하는 글자로 리턴하는 속성 (원본 그대로)
//"swift".capitalized

// 소문자로 변형시키서 비교하는 것은 가능

"swift" == "Swift"   // false

"swift".lowercased() == "Swift".lowercased()    // true

var emptyString = " "    // [공백]이 포함된 문자열

// 문자열은 길이를 기준으로 빈문장열을 판단

emptyString.count     // 1
emptyString.isEmpty   // false

emptyString = ""     // [빈] 문자열    (nil이 절대 아님)

emptyString.count        // 0
emptyString.isEmpty      // true

if emptyString == nil {    // 빈 문자열은 nil이 아님 ===> String타입 (O)   String?타입 (X)
    print("nil")
}

String의 인덱스(색인/순번) 타입

  • 문자열도 Collection 프로토콜(Array / Dictionary / Set)을 따르고 있음 ➞ 데이터바구니

문자열의 인덱스는 정수가 아님 ⭐️

  • (스위프트는 문자열을 글자의 의미단위로 사용하기 때문에, 정수 인덱스 사용 불가)

[String.Index 타입]

  • 문자열.startIndex
  • 문자열.endIndex
  • 문자열.index(<#T##i: String.Index##String.Index#>, offsetBy: <#T##String.IndexDistance#>)
  • 문자열.index(after: <#T##String.Index#>)
  • 문자열.index(before: <#T##String.Index#>)
  • (다만, 인덱스의 크기 비교는 당연히 가능)
  • 문자열.indices (인덱스의 모음)
  • (인덱스를 벗어나는 것에 주의)
  • 문자열.firstIndex(of: <#T##Character#>)
  • 문자열.lastIndex(of: <#T##Character#>)

[String.Index 범위]

  • 문자열.range(of: <#T##StringProtocol#>)
  • 문자열.range(of: <#T##StringProtocol#>, options: <#T##String.CompareOptions#>, range: <#T##Range<String.Index>?#>, locale: <#T##Locale?#>)
  • String.Index를 이용, 서브스크립트 활용가능 ⭐️

[String.Index의 정수형태로 거리는 측정 가능]

  • 문자열.distance(from: <#T##String.Index#>, to: <#T##String.Index#>)
let greeting = "Guten Tag!"

greeting.startIndex
print(greeting.startIndex)

greeting[greeting.startIndex]    // "G"

// 정수형태를 한번 변형해서(걸러서) 사용하는 방식 ⭐️

var someIndex = greeting.index(greeting.startIndex, offsetBy: 2)
greeting[someIndex]      // "t"

someIndex = greeting.index(greeting.startIndex, offsetBy: 1)
greeting[someIndex]      // "u"

someIndex = greeting.index(after: greeting.startIndex)
greeting[someIndex]      // "u"

someIndex = greeting.index(before: greeting.endIndex)
greeting[someIndex]      // "!"

for index in greeting.indices {       // 개별 문자의 인덱스에 접근
    print("\(greeting[index]) ", terminator: "")
}
print("")

//======================================== 출력결과는 동일하지만 접근법이 다름
for char in greeting {
    print("\(char) ", terminator: "")
}
//========================================

// 공백 문자열 다음의 글자를 알고 싶을때

var firstIndex = greeting.firstIndex(of: " ")!
var nextOfEmptyIndex = greeting.index(firstIndex, offsetBy: 1)
greeting[nextOfEmptyIndex]

// 세번째 글자를 알고 싶을때

var thirdCharIndex  = greeting.index(greeting.startIndex, offsetBy: 2)           // 스타트 인덱스에서 2만큼 이동한 인덱스로

var thirdCh = greeting[thirdCharIndex]

// 범위를 벗어나면 에러발생 주의 ⭐️

//greeting[greeting.endIndex]
greeting[greeting.index(greeting.endIndex, offsetBy: -1)]
//greeting[greeting.index(before: greeting.endIndex)]

// 예를 들자면, 아래와 같이 올바른 범위에서 실행

someIndex = greeting.index(greeting.startIndex, offsetBy: 7)

if greeting.startIndex <= someIndex && someIndex < greeting.endIndex { // 범위를 벗어나지 않는 경우 코드 실행
    print(greeting[someIndex])
}

// indices를 직접 출력해보기

for i in greeting.indices {
    print(i)
}

//let greeting = "Guten Tag!"

// 문자열 특정범위를 추출

let lower = greeting.index(greeting.startIndex, offsetBy: 2)
let upper = greeting.index(greeting.startIndex, offsetBy: 5)
greeting[lower...upper]

// 실제로는 뒤에서 배울, 교체/삭제에서 주로 범위를 활용

var range = greeting.range(of: "Tag!")!
greeting[range]

range = greeting.range(of: "tag", options: [.caseInsensitive])!
greeting[range]

// 정수 형태 수치로 거리 측정

var distance = greeting.distance(from: lower, to: upper)
print(distance)

문자열의 삽입/교체/추가/삭제

삽입(insert), 교체(replace), 추가(append), 삭제(remove)

삽입하기

  • insert(_*:,at:)       // 특정인덱스에 문자
  • insert(contentsOf:,at:)    // 특정인덱스에 문자열*
var welcome = "Hello"

welcome.insert("!", at: welcome.endIndex)
// "Hello!"

welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// "Hello there!"

교체하기

  • replaceSubrange(_:,with:)    // 범위기준 교체
  • replacingOccurrences(of:,with:)       //  (존재하면) 해당글자가 있으면 교체 ==> 원본은 그대로
  • replacingOccurrences(of:,with:,options:,range:)
welcome = "Hello there!"
print(welcome)

if let range = welcome.range(of: " there!") {  // 범위를 가지고
    welcome.replaceSubrange(range, with: " Swift!")     // 교체하기
    print(welcome)
}

var newWelcome = welcome.replacingOccurrences(of: "Swift", with: "World")
// "Swift"라는 문자열이 존재하면, "World"로 교체
print(welcome)
print(newWelcome)

                                                                // 대소문자 무시 옵션
newWelcome = welcome.replacingOccurrences(of: "swift", with: "New World", options: [.caseInsensitive], range: nil)
print(welcome)
print(newWelcome)

추가하기

  • 문자열 기본 연산자 + / +=
  • append(_:)
"swift" + "!"  // 너무나 당연

welcome.append("!")
welcome.append(" Awesome!")

삭제하기

  • remove(at:) // 특정인덱스의 문자
  • removeSubrange(_:)       // 특정인덱스의 문자열
  • removeFirst(2)
  • removeLast(2)
  • removeAll()
  • removeAll(keepingCapacity: true)
welcome = "Hello Swift!"

// 인덱스를 가지고 지우기
// (endIndex의 전 인덱스)
welcome.remove(at: welcome.index(before: welcome.endIndex))     // "!" 지우기
welcome
// "Hello Swift"

// 인덱스 범위파악
var range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
//range = welcome.range(of: " Swift")!

// " Swift"의 범위를 파악하고 지우기
welcome.removeSubrange(range)
welcome      // "Hello"

welcome.removeAll()
welcome.removeAll(keepingCapacity: true)
var string = "Hello world"

// 1) " " 공백 문자열의 인덱스 찾기
// 2) " " 공백 문자열의 인덱스에 " super" 삽입하기

if let someIndex = string.firstIndex(of: " ") {
    string.insert(contentsOf: " super", at: someIndex)
    print(string)      // "Hello super world"
}

// 1) 첫 " " 공백 문자열의 인덱스 찾기
// 2) " super" 문자열의 범위 만들기
// 3) 범위 삭제하기

if let firstIndex = string.firstIndex(of: " ") {
    let range = firstIndex...string.index(firstIndex, offsetBy: 5)
    string.removeSubrange(range)
    print(string)     // "Hello world"
}

// 바꿀 문자열을 정확하게 알고 있다면 ===> 범위를 직접 리턴하는 메서드 활용 ⭐️

if let range = string.range(of: " world") {
    string.removeSubrange(range)
    print(string)
}

[Subrange만 반환] 원본은 그대로

  • dropFirst(2) // 앞의 두글자 뺀 나머지 반환
  • dropLast(2) // 뒤의 두글자 뺀 나머지 반환

문자열의 단순 비교

1. 비교연산자 (대소문자 구별)

swift" == "Swift"   // false
"swift" != "Swift"   // true   ===> 둘의 문자는 다른 것임

2. 크기 비교하기 (유니코드 비교)

"swift" < "Swift"      // false ====> 첫 글자의 (유니코드) 순서를 비교
"swift" <= "Swift"     // false ====> 소문자가 (유니코드/아스키코드) 더 뒤에 위치
//"Swift" <= "swift"     // true

3. 대소문자 무시하고 비교는?

// (간단하게는 일치시킨 후 비교)

"swift".lowercased() == "Swift".lowercased()

var a = "swift"
var b = "Swift"

a.caseInsensitiveCompare(b) == ComparisonResult.orderedSame

//문자열.caseInsensitiveCompare(<#T##aString: StringProtocol##StringProtocol#>)

 ComparisonResult 열거형 타입으로 정의  (비교 결과 타입)
  1) .orderedSame          // 동일
  2) .orderedAscending     // 오름차순
  3) .orderedDescending    // 내림차순
 
 - 단순 같은지 틀린지 뿐만아니라, 결과가 오름차순/내림차순인지
   내림차순인지 알수 있어서 결과값이 활용성이 높고 보다 구체적인 정보 제공가능 ⭐️
   (다만, 처음 사용하는 입장에서 헷갈릴 수 있으므로 잘 알고
   사용해야하는 불편함이 있을 수 있음)

문자열에서 일치여부 확인 메서드 사용

일치여부 메서드 사용 → "다양한 옵션"적용이 가능해서 비교를 여러가지 방식으로 활용가능

// 문자열.compare(_:options:range:locale:) ⭐️

var name = "Hello, Swift"

name.compare("hello", options: [.caseInsensitive]) == .orderedDescending    // 내림차순  ( , ==>  )

문자열 비교 옵션(String.CompareOptions)과 비교 결과

String.CompareOptions (비교 옵션)

String.CompareOptions 구조체]와 내부의 타입 속성들

  • .caseInsensitive       // 대소문자 무시하고 ⭐️
  • .diacriticInsensitive  // 발음구별기호 무시하고
  • .widthInsensitive      // 글자 넓이 무시하고
  • .forcedOrdering        // 강제적 오름차순/내림차순 정렬순 (대소문자 무조건 구별 의미)
  • .literal               // (유지코드 자체로) 글자그대로
  • .numeric               // 숫자 전체를 인식해서 비교
  • .anchored              // (앞부분부터) 고정시키고 (접두어)
  • .backwards             // 문자 뒷자리부터
  • .regularExpression     // 정규식 검증 ⭐️
옵션 입력 부분
// OptionSet 프로토콜 채택시, 여러개의 옵션을 배열 형식으로 전달 가능
//NSString.CompareOptions
struct CompareOptions : OptionSet   프로토콜 채택
// .diacriticInsensitive 발음구별기호 무시하고
"café".compare("cafe", options: [.diacriticInsensitive]) == .orderedSame

// .widthInsensitive 글자 넓이 무시하고
"ァ".compare("ァ", options: [.widthInsensitive]) == .orderedSame

// .forcedOrdering 강제적 오름차순/내림차순 정렬순 (대소문자 무조건 구별 의미)
"Hello".compare("hello", options: [.forcedOrdering, .caseInsensitive]) == .orderedAscending

// .numeric 옵션 숫자 전체를 인식해서 비교
"album_photo9.jpg".compare("album_photo10.jpg", options: [.numeric]) == .orderedAscending

// .literal 옵션
"\u{D55C}".compare("\u{1112}\u{1161}\u{11AB}", options: [.literal]) == .orderedSame
// "한"(완성형)     "ㅎ+ㅏ+ㄴ"(조합형)

// .anchored 옵션 (앞부분부터) 고정시키고 (접두어)
if let _ = "Hello, Swift".range(of: "Hello", options: [.anchored]) {   // 범위리턴 ===> 접두어 기능
    print("접두어 일치")
}

// .anchored 옵션 + .backwards 뒷자리부터 고정 (접미어)
if let _ = "Hello, Swift".range(of: "Swift", options: [.anchored, .backwards]) {   // ===> 접미어 기능
    print("접미어 일치")
}

특정문자의 (검색 및) 제거

특정 문자들을 제거할때 사용하기 위한 메서드

  1. 간단하게 앞뒤의 특정 문자를 제거하는 메서드
  • 문자열.trimmingCharacters(in: <#T##CharacterSet#>)
  1. 문자열의 중간에 특정 문자를 제거하는 방법 ⭐️
    "해당 특정 문자"를 기준으로 (잘라서) 문자열을 배열로 ===> (다시 배열을) 문자열로
  • 문자열.components(separatedBy: <#T##CharacterSet#>).joined()

앞뒤의 공백문자의 제거

var userEmail = " my-email@example.com "

var trimmedString = userEmail.trimmingCharacters(in: [" "])
print(trimmedString)
// "my-email@example.com" (처음, 마지막의 공백 문자열 제거)

// CharacterSet 개념을 활용해서
trimmedString = userEmail.trimmingCharacters(in: .whitespaces)
print(trimmedString)

앞뒤의 특정문자의 제거

var someString = "?Swift!"
var removedString = someString.trimmingCharacters(in: ["?","!"])
print(removedString)

someString = "?Swi!ft!"
removedString = someString.trimmingCharacters(in: ["?","!"])
print(removedString)       // 중간에 있는 !는 제거하지 못함

(중간에 포함된)공백문자의 제거

var name = " S t e v e "
var removedName = name.components(separatedBy: " ").joined()    //["", "S", "t", "e", "v", "e", ""]
print(removedName)

(중간에 포함된)특수문자의 제거

var phoneNum = "010-1234-1234"
var newPhoneNum = phoneNum.components(separatedBy: "-").joined()   // ["010", "1234", "1234"]
print(newPhoneNum)

여러개의 특수문자를 한꺼번에 제거

var numString =  "1+2-3*4/5"
var removedNumString =  numString.components(separatedBy: ["+","-","*","/"]).joined()
print(removedNumString)

components(separatedBy:)와 거의 동일한 메서드 split(separator:) 그러나 차이는 있음

var str =  "Hello Swift"
var arr = str.split(separator: " ")    // 서브스트링으로 리턴함
print(arr)
print(arr.joined())

// - (1) split은 Substring 배열로 리턴
str.split(separator: " ")

// - (2) split은 클로저를 파라미터로 받기도 함 (클로저에서 원하는 함수내용을 정의하면 되므로 활용도가 더 높을 수 있음)
str.split { $0 == " " }

//str.split(whereSeparator: <#T##(Character) throws -> Bool#>)

(미리 정의된) 특정 문자 집합(Set)의 개념을 이용하면, 조금 더 편하게 사용가능

  • 구조체로 구현되어 있는
  • 문자집합 (문자열 검색, 잘못된 문자 삭제 등에 주로 활용) (기본적인 Set성격)

[CharacterSet] 유니코드 기준

  • .symbols // 기호
  • .alphanumerics // 문자 + 숫자
  • .decimalDigits // 10진법 숫자
  • .letters // 문자 (유니코드상 Letter, Mark 카테고리 해당 문자)
  • .lowercaseLetters // 소문자
  • .uppercaseLetters // 대문자 ["A", "B", "C", "D", "E" ...]
  • .whitespaces // 공백문자 [" "]
  • ....등등
참고: https://developer.apple.com/documentation/foundation/characterset
============================================**/

// 문자셋을 활용해서

userEmail = " my-email@example.com "

var characterSet = CharacterSet.whitespaces   // 공백문자 집합

trimmedString = userEmail.trimmingCharacters(in: characterSet)
print(trimmedString)

name = " S t e v e "

removedName = name.components(separatedBy: characterSet).joined()
print(removedName)

var phoneNumbers = "010 1111 2222"
print(phoneNumbers.components(separatedBy: .whitespaces).joined())

특정 문자열 검색에도 활용가능

name = "hello+world"

if let range = name.rangeOfCharacter(from: .symbols) {
    print(name[range])
}
profile
iOS 개발자 공부하는 Roy

0개의 댓글