note.nkmk.me

Pythonで半角1文字、全角2文字として文字数(幅)カウント

Date: 2017-11-12 / tags: Python, 文字列操作, Unicode

Pythonで半角を1文字、全角を2文字として文字列の文字数(文字幅)をカウントしたい場合、標準モジュールunicodedataの関数east_asian_width()を使う。

このunicodedata.east_asian_width()を使うことでUnicode文字に割り当てられたEast Asian Widthの値が取得できる。この値を使うと、その文字が半角か全角かを判定できる。

スポンサーリンク

East Asian Widthとは

East Asian Widthについては、Wikipediaの該当ページが詳しい。

「東アジアの文字幅」(英: East Asian Width)は、Unicode標準の附属書 (英: Unicode Standard Annex) の一つ。Unicodeに収録されている各文字の文字幅に関するヒントを与える East_Asian_Width 参考特性(英: informative property)を定めている。
東アジアの文字幅 - Wikipedia

附属書自体へのリンクは以下。

アラビア文字とかロシア語に使われるキリル文字とかまで考慮すると複雑になるが、とりあえず日本語を対象にする場合、East Asian Widthが、

  • F, W, Aは全角(= 2文字分)
  • H, Na, Nは半角(= 1文字分)

として扱えばよい。

unicodedata.east_asian_width()の使用例

unicodedata.east_asian_width()の動きを確認する。全角かなを渡すとWが文字列str型として返ってくる。

import unicodedata

print(unicodedata.east_asian_width('あ'))  # 全角かな
print(type(unicodedata.east_asian_width('あ')))
# W
# <class 'str'>

半角英数はNa、全角英数はF、半角カナはH、特殊な文字はAが返ってくる。

print(unicodedata.east_asian_width('a'))  # 半角英数
# Na

print(unicodedata.east_asian_width('A'))  # 全角英数
# F

print(unicodedata.east_asian_width('ア'))  # 半角カナ
# H

print(unicodedata.east_asian_width('Å'))  # 特殊文字(例: オングストローム)
# A

もし日本語以外の言語を使う場合は、unicodedata.east_asian_width()でどんな値が返ってくるか確認してみるといいだろう。

半角を1文字、全角2を文字としてカウントするコード例

以下のような関数を定義すると、半角を1文字、全角を2文字として文字列の文字数をカウントできる。F, W, Aは全角(= 2文字分)、H, Na, Nは半角(= 1文字分)として数えている。

import unicodedata

def get_east_asian_width_count(text):
    count = 0
    for c in text:
        if unicodedata.east_asian_width(c) in 'FWA':
            count += 2
        else:
            count += 1
    return count
source: strlib.py

文字列を入力してみるとこんな感じ。所望の結果が得られている。

print(get_east_asian_width_count('あいうえお'))
# 10

print(get_east_asian_width_count('abcde'))
# 5

print(get_east_asian_width_count('アイウエオ'))
# 5

print(get_east_asian_width_count('abcde'))
# 10

print(get_east_asian_width_count('あアaa'))  # 全角2文字(あ, a)、半角2文字(ア, a)
# 6

注意点

上述のWikipediaのページにも記載があるように、A(Ambiguous: 曖昧)やN(Neutral: 中立)は定義が一貫していない。日本語と基本的な英数字のみを対象とする場合は問題ないが、アクセント付きの文字などを扱う場合は注意が必要。

従来文字コードとの互換性を目的としているため、Unicode全体から見たとき、特性値NやAの付与は一貫していない部分がある。東アジアのどの文字集合規格にも含まれたことのない用字 (コプト文字、デーヴァナーガリーなど) は、すべて特性値N(中立)である。いっぽう、ひとつの用字系の中でも、収録されたかどうかで個々の文字の特性値が異なっている。たとえばラテン文字では、アクセントなしのものは特性値Na(狭)となるが、アクセントつきのものは小文字の一部(á、ě 等)がGB2312などに収録されているため特性値A(曖昧)となり、大文字のほとんど (Á, Ě など) は東アジアの文字集合規格に収録されていないため特性値N(中立)となる。
東アジアの文字幅 - Wikipedia

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事