← Back to archive

Development · iOS

Choosing Korean particles in Swift

Inspect the final Hangul syllable to choose the correct Korean subject particle.

Read the Korean original on Velog ↗English translation

Development archive cover

Even adding a subject particle after a user name can sound wrong if the final consonant is ignored. The choice between ‘이’ and ‘가’ can be made from the last Hangul syllable's Unicode value without a dictionary.

Hangul and Unicode

Unicode contains 11,172 precomposed Hangul syllables, from 0xAC00 (가) through 0xD7A3 (힣).

Syllables: U+AC00–U+D7A3 (가–힣)

Each syllable consists of an initial consonant, a vowel, and an optional final consonant, called a batchim.

Initial consonants: U+1100–U+1112
Vowels: U+1161–U+1175
Final consonants: U+11A8–U+11C2

A Hangul syllable can be stored as a precomposed character or as a sequence of its constituent jamo.

let first = "\u{1100}\u{1161}" // "가", composed of initial ㄱ and vowel ㅏ
let second = "\u{ac00}" // The syllable "가"
let third = "가" // The character "가"

first == second // true
second == third // true
third == first // true
  • In Swift, write a Unicode scalar using its hexadecimal value inside \u{ }.
  • The prefix 0x indicates a hexadecimal number.

Starting at 0xAC00, the syllable code is calculated from 19 initial consonants, 21 vowels, and 28 final-consonant positions, including the position for no final consonant.

((initialIndex * 21) + vowelIndex) * 28 + finalIndex + 0xAC00 = syllableCode

Reversing the calculation gives the initial, vowel, and final-consonant indices for a syllable.

initialIndex = ((syllableCode - 0xAC00) / 28) / 21
vowelIndex = ((syllableCode - 0xAC00) / 28) % 21
finalIndex = (syllableCode - 0xAC00) % 28

Appending the correct particle

The following steps choose and append a subject particle based on the final syllable.

1. Extract the final character.
2. Convert it to a numeric Unicode scalar value.
3. Calculate the final-consonant index and choose the particle based on whether it is zero.

Get the final character

Use .last to extract the final character of the input. Because an empty string has no last character, unwrap the optional result before continuing.

func addKoreanParticle(_ input: String) -> String {
	// Unwrap the final character
    guard let text = input.last { return input }
}

Read the Unicode value

Convert the character into a numeric Unicode scalar value so the final-consonant index can be calculated. UnicodeScalar(String(text))?.value is optional and must be unwrapped as well.

func addKoreanParticle(_ input: String) -> String {
    guard let text = input.last { return input }
    // Unwrap the numeric Unicode scalar value
    let val = UnicodeScalar(String(text))?.value
    guard let value = val else { return input }
}

Calculate the final-consonant index

Calculate the index from the scalar value using the formula above. An index of 0 means there is no final consonant, so append ‘가’. A nonzero index means a final consonant is present, so append ‘이’. This calculation assumes the character is a precomposed Hangul syllable.

func addKoreanParticle(_ input: String) -> String {

    guard let text = input.last else { return input }
    
    let val = UnicodeScalar(String(text))?.value
    guard let value = val else { return input }
    // Calculate the final-consonant index
    let index = (value - 0xac00) % 28
    // Choose and return the appropriate particle
    if index == 0 {
        return input + "가"
    } else {
        return input + "이"
    }
}

Further reading: Unicode glossary: Hangul syllables.

← Back to archive