Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 한글 문자열 처리 - 한글 관리, 자음, 모음 판단하는 방법 본문

iOS 응용 (swift)

[iOS - swift] 한글 문자열 처리 - 한글 관리, 자음, 모음 판단하는 방법

jake-kim 2023. 11. 28. 01:17

자음, 모음 판단 아이디어

  • 모음은 중성에 해당되고 중성의 리스트만 알고 있으면 contains로 확인이 가능
  • 유니코드 상으로 초성, 중성, 종성이 순서대로 되어 있고 각 시작부분과 개수만 알면 리스트 생성이 손쉽게 가능

초성, 중성, 종성 프로퍼티 생성

  • 변하지 않는 값이기 때문에 enum하위로 static var로 구현
    • * Syllable: 음절
    • * initialConsonant: 초성 (처음 부분의 자음)
    • * medialVowel: 중성 (중간의 모음)
    • * finalConsonant: 종성 (마지막 부분의 자음)
enum Syllable {
    /// ㄱ...ㅎ (19개)
    static var initialConsonantList: [String] {
        ...
    }
    /// ㅏ...ㅣ(21개)
    static var medialVowelList: [String] {
        ...
    }
    /// ㄱㄲ...ㅍㅎ' ' (27 + 1개)
    static var finalConsonantList: [String] {
        ...
    }
}
  • 구하는 방법
    • 첫번째 유니코드 + 각 개수
    • 첫번째 유니코드와 개수를 알아야 하므로 아래처럼 선언
enum Syllable {
    static let startInitialConsonantUnicode = 0x1100
    static let startMedialVowelUnicode = 0x314F
    static let startFinalConsonantUnicode = 0x11A8
    
    static let countOfInitialConsonant: UInt32 = 19
    static let countOfMedialVowel: UInt32 = 21
    static let countOfFinalConsonant: UInt32 = 27
    ...
}
  • 아래처럼 initialConsonantList를 구현
/// ㄱ...ㅎ (19개)
static var initialConsonantList: [String] {
    let startUnicodeScalar = UnicodeScalar(startInitialConsonantUnicode)!
    return (startUnicodeScalar.value..<startUnicodeScalar.value + countOfInitialConsonant).asStrings
            .map { String($0, radix: 16) }
            .compactMap { UnicodeScalar(Int($0, radix: 16) ?? 0) }
    	    .map { String(Character($0)) }
}
  • map, compactMap, map 중복 로직이 될 것이므로 Range<UInt32>로 따로 빼기 
static var initialConsonantList: [String] {
    let startUnicodeScalar = UnicodeScalar(startInitialConsonantUnicode)!
    return (startUnicodeScalar.value..<startUnicodeScalar.value + countOfInitialConsonant).asStrings
}

private extension Range<UInt32> {
    var asStrings: [String] {
        self
        .map { String($0, radix: 16) }
        .compactMap { UnicodeScalar(Int($0, radix: 16) ?? 0) }
        .map { String(Character($0)) }
    }
}
  • 중성, 종성도 마찬가지로 구현
enum Syllable {
    ...
    
    /// ㄱ...ㅎ (19개)
    static var initialConsonantList: [String] {
        let startUnicodeScalar = UnicodeScalar(startInitialConsonantUnicode)!
        return (startUnicodeScalar.value..<startUnicodeScalar.value + countOfInitialConsonant).asStrings
    }
    /// ㅏ...ㅣ(21개)
    static var medialVowelList: [String] {
        let startUnicodeScalar = UnicodeScalar(startMedialVowelUnicode)!
        return (startUnicodeScalar.value..<startUnicodeScalar.value + countOfMedialVowel).asStrings
    }
    /// ㄱㄲ...ㅍㅎ' ' (27 + 1개)
    static var finalConsonantList: [String] {
        let startUnicodeScalar = UnicodeScalar(startFinalConsonantUnicode)!
        return [""] + (startUnicodeScalar.value..<startUnicodeScalar.value + countOfFinalConsonant).asStrings
    }
}

(출력하여 테스트)

print(Syllable.initialConsonantList)
// ["ᄀ", "ᄁ", "ᄂ", "ᄃ", "ᄄ", "ᄅ", "ᄆ", "ᄇ", "ᄈ", "ᄉ", "ᄊ", "ᄋ", "ᄌ", "ᄍ", "ᄎ", "ᄏ", "ᄐ", "ᄑ", "ᄒ"]

print(Syllable.medialVowelList)
// // ["ㅏ", "ㅐ", "ㅑ", "ㅒ", "ㅓ", "ㅔ", "ㅕ", "ㅖ", "ㅗ", "ㅘ", "ㅙ", "ㅚ", "ㅛ", "ㅜ", "ㅝ", "ㅞ", "ㅟ", "ㅠ", "ㅡ", "ㅢ", "ㅣ"]

print(Syllable.finalConsonantList)
// ["", "ᆨ", "ᆩ", "ᆪ", "ᆫ", "ᆬ", "ᆭ", "ᆮ", "ᆯ", "ᆰ", "ᆱ", "ᆲ", "ᆳ", "ᆴ", "ᆵ", "ᆶ", "ᆷ", "ᆸ", "ᆹ", "ᆺ", "ᆻ", "ᆼ", "ᆽ", "ᆾ", "ᆿ", "ᇀ", "ᇁ", "ᇂ"]
  • 이제 isVowel 함수도 생성
enum Syllable {
  ...
  static func isVowel(string: String) -> Bool {
      Self.medialVowelList.contains(string)
  }
}

사용하는 곳)

print(Syllable.isVowel(string: "ㅁ")) // False
print(Syllable.isVowel(string: "ㅏ")) // True
print(Syllable.isVowel(string: "ㅣ")) // True

 

* 참고

- https://ko.wikipedia.org/wiki/%ED%95%9C%EA%B8%80_%EC%9D%8C%EC%A0%88

Comments