อัลกอริทึม

NFD (Canonical Decomposition)

Normalization Form D: แยกส่วนอย่างสมบูรณ์โดยไม่รวมใหม่ ใช้โดยระบบไฟล์ macOS HFS+ é (U+00E9) → e + ◌́ (U+0065 + U+0301)

· Updated

NFD: Decomposing Characters to Their Components

NFD (Normalization Form D — Canonical Decomposition) is the form where every composed character is broken down into its constituent parts: a base character followed by one or more combining marks in canonical order. Unlike NFC which recomposes after decomposing, NFD leaves everything decomposed.

For é (U+00E9, LATIN SMALL LETTER E WITH ACUTE), NFD yields the two-code-point sequence e (U+0065) + ́ (U+0301, COMBINING ACUTE ACCENT). For a string like "über", NFD yields u + combining diaeresis + b + e + r — five code points for a four-character word.

When NFD is Used

NFD is the internal form used by Apple's HFS+ and APFS file systems. When macOS writes a filename to disk, it stores it in NFD. This is why filenames created on a Mac can cause issues when transferred to Linux systems: the file café is stored as 5 code points (NFD) on HFS+ but most Linux applications expect 4 code points (NFC). Python's os module will give you the NFD filename on macOS unless you normalize it.

NFD is also useful when you need to strip diacritics:

import unicodedata

def strip_accents(text: str) -> str:
    # Decompose to base + combining marks, then remove all combining marks
    nfd = unicodedata.normalize("NFD", text)
    return "".join(
        c for c in nfd
        if unicodedata.category(c) != "Mn"  # Mn = Mark, Nonspacing
    )

print(strip_accents("naïve"))   # naive
print(strip_accents("résumé"))  # resume
print(strip_accents("über"))    # uber

Combining Mark Order

A subtle but important aspect of NFD: when multiple combining marks follow a base character, Unicode specifies their Canonical Combining Class (CCC) order. Marks with lower CCC values come first (CCC=0 is the base character). The acute accent has CCC=230, the cedilla has CCC=202. NFD ensures combining marks are always in this canonical order, which is necessary for correct canonical equivalence testing.

import unicodedata

# Check combining class of a character
print(unicodedata.combining("\u0301"))  # 230 (COMBINING ACUTE ACCENT)
print(unicodedata.combining("\u0327"))  # 202 (COMBINING CEDILLA)
print(unicodedata.combining("a"))       # 0   (not a combining mark)

Quick Facts

Property Value
Full name Normalization Form Canonical Decomposition
Algorithm Recursive canonical decomposition, then CCC sorting
macOS HFS+ Filenames stored in NFD
Typical use Diacritic stripping, internal processing, canonical comparison
Python unicodedata.normalize("NFD", s)
Handles compatibility chars? No
Relation to NFC NFD then compose = NFC
String length Equal or longer than NFC (decomposed forms use more code points)

คำศัพท์ที่เกี่ยวข้อง

เพิ่มเติมใน อัลกอริทึม

Case Folding

Mapping characters to a common case form for case-insensitive comparison. More comprehensive …

Grapheme Cluster Boundary

Rules (UAX#29) for determining where one user-perceived character ends and another begins. …

NFC (Canonical Composition)

Normalization Form C: แยกส่วนแล้วรวมใหม่แบบ canonical ได้รูปแบบที่สั้นที่สุด แนะนำสำหรับการจัดเก็บและแลกเปลี่ยนข้อมูล เป็นรูปแบบมาตรฐานของเว็บ

NFKC (Compatibility Composition)

Normalization Form KC: แยกส่วนแบบ compatibility แล้วรวมแบบ canonical รวมอักขระที่มีลักษณะคล้ายกัน (fi→fi, ²→2, Ⅳ→IV) ใช้สำหรับการเปรียบเทียบตัวระบุ

NFKD (Compatibility Decomposition)

Normalization Form KD: แยกส่วนแบบ compatibility โดยไม่รวมใหม่ เป็นการ normalize ที่เข้มงวดที่สุด สูญเสียข้อมูลการจัดรูปแบบมากที่สุด

String Comparison

Comparing Unicode strings requires normalization (NFC/NFD) and optionally collation (locale-aware sorting). Binary …

การทำให้เป็นมาตรฐาน

กระบวนการแปลงข้อความ Unicode เป็นรูปแบบ canonical มาตรฐาน มี 4 รูปแบบ: NFC (รวม), NFD (แยก), …

การยกเว้นการประกอบ

อักขระที่ถูกยกเว้นจากการรวมแบบ canonical (NFC) เพื่อป้องกันการแตกย่อยแบบ non-starter และรับประกันความเสถียรของอัลกอริทึม ระบุไว้ใน CompositionExclusions.txt

การแบ่งส่วนข้อความ

อัลกอริธึมสำหรับค้นหาขอบเขตในข้อความ: ขอบเขต grapheme cluster, คำ และประโยค มีความสำคัญสำหรับการเลื่อนเคอร์เซอร์ การเลือกข้อความ และการประมวลผลข้อความ

ขอบเขตคำ

ตำแหน่งระหว่างคำตามกฎการแบ่งคำของ Unicode ไม่ใช่แค่การแบ่งตามช่องว่าง แต่รองรับ CJK (ไม่มีช่องว่าง) คำย่อ และตัวเลขอย่างถูกต้อง