拡張書記素クラスター
ユーザーが感じる「1文字」—単一の単位として感じられるもの。複数のコードポイント(基本文字+結合記号、または絵文字ZWJシーケンス)で構成される場合があります。👩💻 = 3コードポイント、1書記素。
What Is a Grapheme Cluster?
A grapheme cluster is what a user perceives as a single "character" on screen—what you see when you tap the delete key once or advance the cursor by one position. Unicode code points and user-perceived characters are not the same: a single grapheme cluster may consist of multiple code points.
The Unicode Standard defines Extended Grapheme Clusters (EGC) in Unicode Standard Annex #29. The boundary rules specify when adjacent code points form a single cluster:
- A base character plus any number of combining marks (e.g., a + ́ → á)
- Hangul syllable sequences (L + V + T clusters, e.g., ㄱ + ㅏ + ㄴ → 간)
- Emoji modifier sequences (👋 + skin-tone modifier 🏽 → 👋🏽)
- Flag sequences (regional indicator J + P → 🇯🇵)
- Emoji ZWJ sequences (👨 + ZWJ + 👩 + ZWJ + 👧 → 👨👩👧)
- Emoji presentation sequences (digit + U+FE0F variation selector → 1️⃣)
Grapheme Cluster Iteration in Python
# Python's len() counts code points, not grapheme clusters
flag = "\U0001F1EF\U0001F1F5" # 🇯🇵 Japan flag (J + P regional indicators)
print(len(flag)) # 2 code points
family = "\U0001F468\u200D\U0001F469\u200D\U0001F467" # 👨👩👧
print(len(family)) # 5 code points
# For grapheme-aware string operations, use the 'grapheme' package
# pip install grapheme
try:
import grapheme
print(grapheme.length(flag)) # 1
print(grapheme.length(family)) # 1
# Grapheme-safe slicing
text = "café" # If stored as c + a + f + e + combining acute
nfd = "cafe\u0301"
print(grapheme.length(nfd)) # 4 (user sees 4 characters)
print(len(nfd)) # 5 (5 code points)
except ImportError:
print("Install 'grapheme' package for EGC support")
# Hangul example
hangul = "\u0067\u0041\u002F" # Not Hangul — just example of combining
syllable = "\uAC00" # 가 — precomposed Hangul syllable
jamo = "\u1100\u1161" # ᄀ + ᅡ — jamo sequence = same grapheme
import unicodedata
print(unicodedata.normalize("NFC", jamo) == syllable) # True
Why Grapheme Clusters Matter
Cursor movement and text editing: A text editor must advance the cursor by one grapheme cluster, not one code point. Moving one code point through 👋🏽 (two code points) would split the emoji in half, leaving a broken sequence.
String truncation: Truncating a string to 10 "characters" for display must count grapheme clusters. text[:10] in Python counts code points and may split an emoji sequence.
Regular expressions: The regex \X in PCRE2 and the Python regex package matches a single extended grapheme cluster, enabling grapheme-aware patterns.
Quick Facts
| Property | Value |
|---|---|
| Concept | Extended Grapheme Cluster (EGC) |
| Defined by | Unicode Standard Annex #29 (UAX #29) |
| Python built-in | No (use grapheme package or regex \X) |
| Common pitfall | len(s) counts code points, not clusters |
| Emoji clusters | ZWJ sequences, modifier sequences, flag sequences |
| Hangul | Jamo sequences form single grapheme clusters |
関連用語
プロパティ のその他の用語
文字が最初に割り当てられたUnicodeバージョン。システムやソフトウェアバージョン間での文字サポートを判断するのに役立ちます。
Unicode property (UAX#11) classifying characters as Narrow, Wide, Fullwidth, Halfwidth, Ambiguous, or …
Unicode property controlling how Arabic and Syriac characters connect to adjacent characters. …
Unicode property listing all scripts that use a character, broader than the …
文字を大文字・小文字・タイトルケースに変換するルール。ロケール依存の場合があり(トルコ語のI問題)、1対多のマッピングもあります(ß → SS)。
文字が属する文字体系(例:ラテン、キリル、漢字)。Unicode 16.0は168個のスクリプトを定義し、Scriptプロパティはセキュリティと混在スクリプト検出に重要です。
サポートしていないプロセスで目に見える効果なく無視できる文字で、異体字セレクター・ゼロ幅文字・言語タグなどが含まれます。
名前付きの連続したコードポイント範囲(例:基本ラテン = U+0000〜U+007F)。Unicode 16.0は336個のブロックを定義し、すべてのコードポイントはちょうど1つのブロックに属します。
RTLコンテキストでグリフを水平に反転すべき文字。例:( → )、[ → ]、{ → }、« → »。
すべてのコードポイントを30個のカテゴリ(Lu・Ll・Nd・Soなど)の1つに分類する体系で、7つの主要クラス(文字・記号・数字・句読点・記号・区切り・その他)にグループ化されています。