Python Tech 文字列

Pythonで文字数制限 日本語文字列の長さ取得と切り詰め方法

文字列の処理は特に重要なテクニックですが、言語によって少しずつ仕様が異なります。

Pythonでも、特に日本語などの全角文字を扱う際に、文字列の処理で覚えておいたほうがいいポイントがあります。

今回の記事ではPythonで日本語文字列の

  • 長さを取得する(カウント)方法
  • 文字数制限する(スライス、部分文字列を抽出)方法

をまとめています。日常的に使える知識を再確認しておきましょう。

 

文字列の長さを取得

全角・半角を区別しない(len)

文字列の長さを数えるなら、len関数を使います。

Pythonのlen()は、全角2バイト文字)・半角(1バイト文字)を区別せず、すべて1文字としてカウントします。

# カウント(1バイト文字・2バイト文字を区別しない)
print(len('abcあいう'))  # 6

特殊文字も1文字としてカウントされます。

# 特殊文字
print(len('\n'))    # 1
print(len('\r\n'))  # 2

print(len('\t'))    # 1
print(len('あい\tうえお'))  # 6

例として使っている各文字の意味は以下の通り。

  • \n 改行コード(LF)改行を表す
  • \r 改行コード(CR)Windowsなどで改行コードに使われる
  • \t タブを表す

※バックスラッシュはスラッシュの逆の形であり、違うものなので注意(MacではOptionを押下しながら¥キー)

 

全角・半角を区別する

Pythonの標準関数len()では、全角と半角を区別しないのでした。

全角文字(2バイト)と半角文字(1バイト)を区別するには、unicodedata モジュールを用いて各文字の幅をチェックします。

unicodedataモジュールは、その名の通りユニコード(Unicode)に関するデータセットを持つ。

unicodedata.east_asian_width(chr=[文字]) 

は、渡した文字のeast asian width(東アジアの文字幅)を返す。

返ってくるのは'Na'や'A'といった文字列の形であり、これを元に文字が全角(2バイト)なのか半角(1バイト)なのか判断する。

unicodedata Docs

サンプルとしていくつかの文字を渡したときにどんな値が返ってくるか確認しましょう。

print(unicodedata.east_asian_width('A'))
# Na

print(unicodedata.east_asian_width('あ')) # 全角ひらがな
# W

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

 

このunicodedata.east_asian_widthを使って、全角・半角を区別しながら文字列の長さを返す関数を作ると以下のようになります。

import unicodedata

def length_double_byte_str(text):
    """ 全角・半角を区別して文字列の長さを返す
        """
    count = 0
    for c in text:
        # 全角文字などの2バイト文字は'F','W','A'のいずれかに当てはまるとする
        if unicodedata.east_asian_width(c) in 'FWA':
            count += 2
        else:
            count += 1
    return count

 

呼び出し側

len_str = length_double_byte_str('abcあいう')
print(len_str)      # 9

 

このサンプルでは
‘abc’は半角文字なので合計3、
‘あいう’は全角文字なので合計6としてカウントされています。

 

文字数を制限する(切り詰める)

全角・半角を区別しない

文字列の一部を抽出するのに、最もシンプルなやり方はスライスをつくることです。

text_after = text[start:end]

 

text:文字列の全体
start: 開始位置
end: 終了位置の一つ後
text_after: スライスされた文字列

 

text = '012345'
s_text = text[1:5]
print(s_text)
# 1234

 

文字数を制限(先頭から一定の文字数を数え、それを超えたらカットする)する場合は、単に開始位置を 0 とすればOKです。

text_after = text[0:制限文字数-1]

 

なお、len()と同じように、Pythonはスライスでも全角(2バイト文字)・半角(1バイト文字)を区別せず、どちらも1文字として扱います。

# 一般的な文字列スライス(1バイト文字・2バイト文字を区別しない)
text = 'abcdef'
s_text = text[0:4]  # 添字4の一つ前まで(3)の文字列をスライスで取得
print(s_text)
# abcd

# 半角英数字なら大文字でももちろん同じ結果に
text = 'ABCDEF'
s_text = text[0:4]  
print(s_text)
# ABCD

# スライスは2バイト文字も1文字とカウントされる
text = 'あいうえおかき'
s_text = text[0:4]
print(s_text)
# あいうえ

# 特殊文字も1文字としてカウントされる
text = 'あいう\nえお'
s_text = text[0:5]
print(s_text)
# あいう
# え

 

全角・半角を区別する

Pythonのスライスは全角・半角文字を区別しません。

全角、半角を区別しながら、文字列を切り抜くには unicodedata.east_asian_width を活用します。

unicodedata.east_asian_width は渡した文字の幅を返すので、これで1文字ずつチェックし、所望の長さの文字列を取得します。

以下は全角・半角を区別して文字数制限(切り詰め)をするサンプルです。

def truncate_double_byte_str(text, len):
    """ 全角・半角を区別して文字列を切り詰める
        """
    count = 0
    sliced_text = ''
    for c in text:
        if unicodedata.east_asian_width(c) in 'FWA':
            count += 2
        else:
            count += 1

        # lenと同じ長さになったときに抽出完了
        if count > len:
            break
        sliced_text += c
    return sliced_text

 

呼び出し側

# 1バイト文字は1文字、2バイト文字は2文字としてスライスする場合
text = 'abcあいう'
s_text = truncate_double_byte_str(text, len=5)
print(s_text)
# abcあ

text = 'abcあいう'
s_text = truncate_double_byte_str(text, len=6)
print(s_text)
# abcあ

 

上記サンプルでは、半角を1、全角を2とカウントします。

そのため、len=5でもlen=6でも同じ結果となります。

 

Pythonの学習法について

Python の勉強が辛くなっていませんか?

Pythonは比較的取り組みやすい言語と言われていますが、プログラミング初心者にとっては分からないことだらけ。

ゼロから独学で勉強するのは厳しい道のりです。

今回、様々な現場、システム、言語を経験してきた現役エンジニアの立場から、初心者でも挫折しない学習方法を解説する記事を書きました。もちろん、お金をかけずに習得できる方法も解説しています。

できるだけストレスがかからない勉強法を解説しているので、ぜひ参考にしてみてくださいね。

 

まとめ

Pythonのlen()では全角・半角を区別せずに1文字として文字数をカウントします。一方、全角・半角を区別して文字数を数えるにはunicodedata.east_asian_width を活用します。

日本語の2バイト文字を2文字として文字数制限をするには上記テクニックを使うといいでしょう。

  • この記事を書いた人

次世代ペンギン

長いのでペンギンとお呼びください。システム開発・プログラミングのお仕事をしています。甘味とコーヒーは生命線。多くの人に役立つ情報のシェアが目標です。

人気の記事

1

会社員でプログラマーとして働いている人、インフラやネットワークのエンジニアとして働いている人の中には、フリーランスのプログラマーとして独立、もしくは転向したい人もいるので ...

2

キャリアアップのため、または高収入を目指して、しっかりプログラミングを学びたいという人が増えてきましたね。 この記事では現役のエンジニアである私が、実際に仕事で稼げるよう ...

3

フリーランスのプログラマーにとって収入の向上に最も直結するのはスキルです。 必要なスキル、スキルの獲得方法が気になる人も多いでしょう。 また、これからフリーランスを目指す ...

4

Vuetifyの v-progress-circular コンポーネントは、数値データや処理状況を環状(円状)のデザインで教えてくれるUIデザインです。 ローディングのス ...

5

Vuexのstore(ストア)を使うと、各コンポーネント間で個別にデータのやり取りすることなく、データを一元的に管理できます。Vueでは欠かせない機能といえるでしょう。 ...

-Python, Tech, 文字列
-,