Pythonで半角1文字、全角2文字として文字数(幅)カウント
Pythonで半角を1文字、全角を2文字として文字列の文字数(文字幅)をカウントしたい場合、標準モジュールunicodedata
の関数east_asian_width()
を使う。
このunicodedata.east_asian_width()
を使うことでUnicode文字に割り当てられたEast Asian Width
の値が取得できる。この値を使うと、その文字が半角か全角かを判定できる。
ここでは、以下の内容について説明する。
- East Asian Widthとは
unicodedata.east_asian_width()
の使用例- 半角を1文字、全角2を文字としてカウントするコード例
- 注意点
なお、半角も全角も1文字として文字数をカウントしたい場合は組み込み関数len()
を使えばよい。特殊文字の扱いなどの詳細は以下の記事を参照。
- 関連記事: Pythonで文字列の長さ(文字数)を取得
文字列から漢字・ひらがな・カタカナ・英数字を抽出してカウントしたい場合は以下の記事を参照。
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文字分)として数えている。
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
文字列を入力した結果は以下の通り。所望の結果が得られている。
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