[Swift] 문자열 처리와 함수 활용 기초 정리
- 1. 문자열 정리
- 1. 문자 하나 추출
- 2. 앞/뒤에서 문자열 일부 추출 (
prefix
,suffix
) - 3. 특정 위치 기준으로 자르기
- 4. 조건 만족 전까지 자르기 (
prefix(while:)
) - 5. 범위를 이용한 부분 문자열 추출
- 6. Substring → String 변환 (swift 4부터 deprecated)
- 7. 문자열에 문자 추가
- 8. 접두어 / 접미어 확인
- Copy-on-Write - Swift의
String
,Array
등은 복사를 지연시키고, 값을 수정할 때 진짜 복사(copy)가 일어남 - 9. 문자열 추가 (
append
,appending
) - 10. 포맷 문자열 추가 (
appendingFormat
) - 11. 문자열 삽입 (
insert
,insert(contentsOf:)
) - 12. 문자열 치환 (
replaceSubrange
) - 13. 문자열 복사 후 치환 (
replacingCharacters
) - 14. 문자열 전역 치환 (
replacingOccurrences
) - 15. 문자열 비교 (대소문자 구분 없이)
- 16. 문자열 삭제 (
remove
,removeSubrange
,removeAll
) - 17. 부분 문자열 제거 (
dropFirst
,dropLast
)
- 2. CharacterSet
- 3. Compare
- 4. Function / Closure
1. 문자열 정리
1. 문자 하나 추출
개념:
String
은 배열처럼 인덱스 접근이 불가능해서 startIndex
등을 이용해야 함
예제:
let str = "Hello Swift"
let firstChar = str[str.startIndex] // "H"
2. 앞/뒤에서 문자열 일부 추출 (prefix
, suffix
)
개념:
prefix(_:)
, suffix(_:)
를 사용하면 문자열 앞/뒤에서 원하는 개수만큼 추출 가능
예제:
str.prefix(2) // "He"
str.suffix(3) // "ift"
3. 특정 위치 기준으로 자르기
개념:
prefix(upTo:)
, prefix(through:)
, suffix(from:)
으로 특정 인덱스를 기준으로 자를 수 있음
예제:
let index = str.index(str.startIndex, offsetBy: 5)
str.prefix(upTo: index) // "Hello"
str.prefix(through: index) // "Hello "
str.suffix(from: index) // " Swift"
4. 조건 만족 전까지 자르기 (prefix(while:)
)
개념:
조건에 따라 앞에서부터 자르며, 조건을 처음으로 만족하지 않을 때 멈춤
예제:
str.prefix(while: { $0 != "i" }) // "Hello Sw"
5. 범위를 이용한 부분 문자열 추출
개념:
String.Index
를 이용해 범위를 지정하면 원하는 구간을 추출할 수 있음
예제:
let part1 = str[str.startIndex ..< str.index(str.startIndex, offsetBy: 2)] // "He"
let part2 = str[str.index(str.startIndex, offsetBy: 2)...] // "llo Swift"
6. Substring → String 변환 (swift 4부터 deprecated)
개념:
prefix
, suffix
등은 Substring
타입을 반환하므로, 수정이 필요하면 String()
으로 변환해야 함
예제:
let sub = str.prefix(4)
let newStr = String(sub) // "Hell"
7. 문자열에 문자 추가
개념:
Substring
은 수정 불가능하므로 String
으로 변환 후 insert
, append
등을 사용
예제:
var first = String(str.prefix(1)) // "H"
first.insert("!", at: first.endIndex) // "H!"
8. 접두어 / 접미어 확인
개념:
hasPrefix
, hasSuffix
로 문자열이 특정 텍스트로 시작하거나 끝나는지 확인 가능 (대소문자 구분)
예제:
str.hasPrefix("Hello") // true
str.hasPrefix("hello") // false
str.hasSuffix("Swift") // true
Copy-on-Write - Swift의 String
, Array
등은 복사를 지연시키고, 값을 수정할 때 진짜 복사(copy)가 일어남
예제:
var a = "Hello"
var b = a // 복사 아님 (메모리 공유)
b += " Swift" // 여기서 진짜 복사 발생
print(a) // "Hello"
print(b) // "Hello Swift"
9. 문자열 추가 (append
, appending
)
개념:
append(_:)
: 원본 문자열에 직접 추가 (mutating)appending(_:)
: 새로운 문자열을 반환 (non-mutating)
예제:
var str = "Hello"
str.append(", ") // "Hello, "
let s = str.appending("Swift") // "Hello, Swift"
10. 포맷 문자열 추가 (appendingFormat
)
개념:
숫자나 포맷이 필요한 텍스트를 문자열에 추가할 때 사용
예제:
let fileSize = "File Size: ".appendingFormat("%.1f", 12.3456) // "File Size: 12.3"
11. 문자열 삽입 (insert
, insert(contentsOf:)
)
개념:
특정 위치에 문자 또는 문자열을 삽입
예제:
str = "Hello Swift"
str.insert(",", at: str.index(str.startIndex, offsetBy: 5)) // "Hello, Swift"
if let sIndex = str.firstIndex(of: "S") {
str.insert(contentsOf: "Awesome", at: sIndex) // "Hello, AwesomeSwift"
}
12. 문자열 치환 (replaceSubrange
)
개념:
특정 문자열 범위를 찾아서 다른 문자열로 교체 (mutating)
예제:
str = "Hello, Objective-C"
if let range = str.range(of: "Objective-C") {
str.replaceSubrange(range, with: "Swift") // "Hello, Swift"
}
13. 문자열 복사 후 치환 (replacingCharacters
)
개념:
문자열을 수정하지 않고 교체된 새 문자열을 반환
예제:
if let range = str.range(of: "Hello") {
let s = str.replacingCharacters(in: range, with: "Hi") // "Hi, Swift"
}
14. 문자열 전역 치환 (replacingOccurrences
)
개념:
문자열 전체에서 해당 문자열을 찾아 모두 교체 (non-mutating)
예제:
var result = str.replacingOccurrences(of: "Swift", with: "Awesome Swift")
// 대소문자 구분 없이
result = str.replacingOccurrences(of: "swift", with: "Awesome Swift", options: [.caseInsensitive])
15. 문자열 비교 (대소문자 구분 없이)
개념:
lowercased()
,uppercased()
로 변환 후 비교caseInsensitiveCompare
로 직접 비교 가능
예제:
"apple".lowercased() == "Apple".lowercased() // true
"apple".caseInsensitiveCompare("Apple") == .orderedSame // true
16. 문자열 삭제 (remove
, removeSubrange
, removeAll
)
개념:
문자열의 특정 문자, 범위 또는 전체 삭제
예제:
str = "Hello, Awesome Swift!!!"
let removed = str.remove(at: str.index(before: str.endIndex)) // 마지막 문자 제거
str.removeFirst() // 첫 문자 제거
str.removeLast() // 마지막 문자 제거
if let range = str.range(of: "Awesome") {
str.removeSubrange(range) // 특정 문자열 제거
}
str.removeAll() // 전체 문자열 삭제
str.removeAll(keepingCapacity: true) // 메모리는 유지
17. 부분 문자열 제거 (dropFirst
, dropLast
)
개념:
원본 문자열은 유지하면서 앞/뒤에서 원하는 수만큼 문자 제거한 Substring 반환
예제:
str = "Hello, Awesome Swift!!!"
let substr1 = str.dropLast() // "Hello, Awesome Swift!!"
let substr2 = str.dropLast(3) // "Hello, Awesome Swift"
let substr3 = str.dropFirst() // "ello, Awesome Swift!!!"
let substr4 = str.dropFirst(2) // "llo, Awesome Swift!!!"
2. CharacterSet
1. 대문자 문자셋 & 반전 (CharacterSet.uppercaseLetters
, inverted
)
개념:
CharacterSet.uppercaseLetters
: A~Z 대문자 집합.inverted
: 해당 집합을 제외한 나머지 문자로 구성된 집합
예제:
let a = CharacterSet.uppercaseLetters
let b = a.inverted
2. 문자열 양쪽 공백 제거 (trimmingCharacters
)
개념:
- 문자열 양 끝의 지정된 문자셋(주로 공백)을 제거
- 원본을 수정하지 않고 새로운 문자열 반환
예제:
let str = " A p p l e "
let trimmed = str.trimmingCharacters(in: .whitespaces) // "A p p l e"
3. 문자열 내 모든 공백 제거 (replacingOccurrences
)
개념:
- 특정 문자열(예:
" "
)을 모두 제거 - 중간 공백 포함 전체 제거 가능
예제:
let noSpaces = str.replacingOccurrences(of: " ", with: "") // "Apple"
4. 문자셋 편집 (insert
, remove
)
개념:
- 문자셋에 특정 문자를 삽입/제거 가능
charactersIn:
을 통해 다중 문자도 추가/제거 가능
예제:
var editTarget = CharacterSet.uppercaseLetters
editTarget.insert("#")
editTarget.insert(charactersIn: "~!@")
editTarget.remove("#")
editTarget.remove(charactersIn: "~!@")
5. 문자열 분리 (components(separatedBy:)
)
개념:
문자셋을 기준으로 문자열을 나누어 배열로 반환
예제:
swift
복사편집
let email = "user@email.com"
let customCharSet = CharacterSet(charactersIn: "@.")
let components = email.components(separatedBy: customCharSet)
// ["user", "email", "com"]
6. 이메일 유효성 검사
개념:
- 알파벳, 숫자,
@
와.
외의 문자가 있는지 검사 .inverted
를 이용해 허용되지 않은 문자 존재 여부 확인
예제:
swift
복사편집
func isValidEmail(_ email: String) -> Bool {
let allowedSet = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "@."))
return email.rangeOfCharacter(from: allowedSet.inverted) == nil
}
isValidEmail("user@email.com") // true
isValidEmail("user#email.com") // false
7. 강력한 비밀번호 유효성 검사
개념:
- 최소 길이 8자 이상
- 대문자, 소문자, 숫자, 특수문자 각각 하나 이상 포함 여부 검사
예제:
swift
복사편집
func strongPassWord(_ password: String) -> Bool {
guard password.count >= 8 else { return false }
let hasUppercase = password.rangeOfCharacter(from: .uppercaseLetters) != nil
let hasLowercase = password.rangeOfCharacter(from: .lowercaseLetters) != nil
let hasDigit = password.rangeOfCharacter(from: .decimalDigits) != nil
let hasPunctuation = password.rangeOfCharacter(from: .punctuationCharacters) != nil
return hasUppercase && hasLowercase && hasDigit && hasPunctuation
}
strongPassWord("Password123!") // true
strongPassWord("pass123") // false
3. Compare
1. 대소문자 구분 문자열 비교 (==
, caseInsensitiveCompare
, compare
)
개념:
==
: 두 문자열이 대소문자 구분하여 동일한지 비교caseInsensitiveCompare
: 대소문자 구분 없이 비교compare(options:)
: 옵션을 설정하여 대소문자 구분 여부를 지정해 비교
예제:
let bigA = "Apple"
let smallA = "apple"
bigA == smallA // false
bigA.caseInsensitiveCompare(smallA) == .orderedSame // true
bigA.compare(smallA, options: [.caseInsensitive]) == .orderedSame // true
2. 사전식 비교 (<
, asciiValue
)
개념:
- 문자열은 유니코드(또는 ASCII) 값을 기준으로 사전식으로 비교
- ASCII 값이 더 작은 문자는 사전에서 더 앞에 옴
asciiValue
:Character
타입의 ASCII 값을 반환
예제:
let bigA = "Apple"
let smallA = "apple"
bigA < smallA // true
("A" as Character).asciiValue // 65
("a" as Character).asciiValue // 97
3. 문자열 포함 여부 확인 (contains
)
개념:
contains
: 대소문자를 구분하여 문자열에 특정 값이 포함되어 있는지 확인lowercased().contains
: 대소문자 구분 없이 비교하려면, 문자열을 모두 소문자(또는 대문자)로 변환한 후 비교
예제:
let str = "Hello, Swift"
str.contains("Swift") // true
str.contains("swift") // false
str.lowercased().contains("swift".lowercased()) // true
4. 문자열 범위 검색 (range(of:)
)
개념:
range(of:)
: 문자열에서 특정 부분을 찾아Range
객체를 반환options
:.caseInsensitive
옵션을 사용하여 대소문자를 구분하지 않도록 할 수 있음
예제:
let str = "Hello, Swift"
str.range(of: "swift", options: [.caseInsensitive]) // true
4. Function / Closure
1. 함수 표기법 (Function Notation)
개념:
- 함수 가리키기를 함수 표기법(Function Notation)이라고 함
- 함수 자체를 호출하지 않고 가리키는 경우를 의미
// 함수 정의
func sayHello() {
print("Hello, Swift")
}
// 함수 표기법: 함수 자체를 가리킴
let f1 = sayHello
//f1() // 함수 호출은 되지 않음
예제:
2. 함수는 First-class Citizen
개념:
- Swift에서 함수는 First-class Citizen이다. 즉, 함수는 다음과 같은 방식으로 다룰 수 있다:
- 변수나 상수에 저장 가능
- 함수의 파라미터로 전달 가능
- 함수의 리턴값으로 반환 가능
예제:
// 함수 정의
func sayHello() {
print("Hello, Swift")
}
// 함수는 First-class Citizen 이므로 변수에 저장할 수 있음
let f1 = sayHello
f1() // 함수 호출
// 파라미터로 전달하거나 리턴할 수도 있음
func printHello(with name: String) {
print("Hello \(name)")
}
let f2: (String) -> () = printHello(with:)
f2("Swift") // "Hello Swift" 출력
3. 함수 타입에 따른 변수 할당
개념:
- 함수의 이름만 있으면 그 함수 타입에 맞는 변수나 상수에 할당할 수 있음
- 함수의 매개변수 이름과 상관없이 같은 함수 타입이라면 동일한 변수나 상수에 할당 가능
예제:
// 함수 정의
func printHello(with name: String) {
print("Hello \(name)")
}
func printHello2(from name: String) {
print("Hello \(name)")
}
// 동일한 타입을 가지므로 f3에 할당 가능
let f3 = printHello(with:)
f3("Swift") // "Hello Swift" 출력
4. 함수 타입에 맞는 변수 할당 예제
개념:
- Argument Label이 다르더라도 함수 타입이 같으면 같은 변수나 상수에 할당 가능
예제:
func add(a: Int, b: Int) -> Int {
return a + b
}
func add(_ a: Int, with b: Int) -> Int {
return a + b
}
// 함수 타입이 같다면 Argument Label이 다르더라도 같은 변수에 할당 가능
var f4: (Int, Int) -> Int = add(a:b:)
f4(1, 2) // 3
f4 = add(_:with:)
f4(1, 2) // 3
5. 함수는 모두 클로저 (Closure)
개념:
- Swift에서 모든 함수는 클로저이다.
- 함수는 이름을 가진 클로저이고, 익명 함수는 이름이 없는 클로저라고 할 수 있음
예제:
// 이름이 있는 함수 (named Closure)
let c = { print("Hello") }
c() // "Hello" 출력
// 이름이 없는 클로저 (익명 함수)
let c2 = { (str: String) -> String in
return "Hello \(str)"
}
c2("Swift") // "Hello Swift" 출력