🙆
【Python】NFD の濁音・半濁音を NFC に変換する
Unicode 正規化には unicodedata.normalize
を使う
python3
>>> import unicodedata
>>> str = 'か\u3099'
>>> len(str)
2
>>> ret = unicodedata.normalize('NFC', str)
>>> len(ret)
1
>>> str2 = 'が'
>>> len(str2)
1
>>> ret2 = unicodedata.normalize('NFD', str2)
>>> len(ret2)
2
Unicode 正規化を行う場合、無関係な文字を巻き込まないようにする必要がある。次のコードは旧字体が新字体に置き換わってしまう例である。
>>> unicodedata.normalize('NFC', '神')
'神'
>>> unicodedata.normalize('NFD', '神')
'神'
絞り込みのために regex を導入する
python -m pip install regex
まずは濁音・半濁音をマッチさせる
>>> import regex
>>> pattern = regex.compile(r'[\p{Script=Hiragana}\p{Script=Katakana}][\u3099\u309A]')
>>> pattern.findall('ハ\u309Aハ\u309Aと神')
['パ', 'パ']
書記素クラスターにマッチさせるには \X
を使う
>>> pattern = regex.compile(r'\X')
>>> pattern.findall('ハ\u309Aハ\u309A')
['パ', 'パ']
リスト内包式で展開してみる
>>> str = 'ハ\u309Aハ\u309Aと神'
>>> iter = regex.compile(r'\X').finditer(str)
>>> [m.group() for m in iter]
['パ', 'パ', 'と', '神']
処理をまとめる。ラムダ式でかなと濁点・半濁点の文字を検出する処理とそれらを限定して Unicode 正規化する関数を定義する
>>> is_nfd_dakuon = lambda str: regex.compile(r'[\p{Script=Hiragana}\p{Script=Katakana}][\u3099\u309A]').match(str)
>>> dakuon_normalize = lambda str: unicodedata.normalize('NFC', str) if is_nfd_dakuon(str) else str
テストの文字列を用意する。書記素単位で取り出すのにリスト内包式を使う
>>> str = 'ハ\u309Aハ\u309Aと神'
>>> iter = regex.compile(r'\X').finditer(str)
>>> [m.group() for m in iter]
['パ', 'パ', 'と', '神']
コードポイントの数も数える
>>> iter = regex.compile(r'\X').finditer(str)
>>> [len(m.group()) for m in iter]
[2, 2, 1, 1]
最後に実際に Unicode 正規化を実施する
>>> [dakuon_normalize(m.group()) for m in iter]
['パ', 'パ', 'と', '神']
>>> [len(dakuon_normalize(m.group())) for m in iter]
[1, 1, 1, 1]
Discussion