いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Pythonメモ-00 (マルチバイトを考慮した文字幅を取得)(unicodedata, east_asian_width, multibytes, WF)

スクリプト書いていると、等幅フォント上で全角半角混じった文字列をピシッと

揃えたいときがよくあります。pythonのlen()は文字数を返すので、それでイケルと思ってしまいますが

s = 'hello'
len(s)

5                # OK

s = 'こんにちわ'
len(s)

5                # (´・ω・`)

max_width = max(len(s) for s in ['hello world', 'こんにちわ世界', 'ABCDE'])
print(max_width)

11

for x in ['hello world', 'こんにちわ世界', 'ABCDE']:
    print(f'{x}{" " * (max_width - len(x))}: xxxxx')
    
hello world: xxxxx
こんにちわ世界: xxxxx
ABCDE      : xxxxx

となってしまいます。全角は2文字分の幅ですよーって

知りたいので、unicodedataモジュールのeast_asian_widthを使います。

def unicode_width(s: str) -> int:
    """
    マルチバイトを考慮した文字幅を返します。

    :param s: 対象文字列
    :return: 文字幅
    """
    return sum([east_asian_width(c) in 'WF' and 2 or 1 for c in s])
for x in ['hello world', 'こんにちわ世界', 'ABCDE']:
    print(f'{x}{" " * (max_width - unicode_width(x))}: xxxxx')

hello world   : xxxxx
こんにちわ世界: xxxxx
ABCDE         : xxxxx

ブラウザで見ると、ずれて見えちゃうかもなので、画像で。

f:id:gsf_zero1:20170318180328p:plain


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。