ホームページ  >  記事  >  バックエンド開発  >  文字幅を計算するPythonメソッド

文字幅を計算するPythonメソッド

WBOY
WBOYオリジナル
2016-06-16 08:47:513712ブラウズ

この記事の例では、Python で文字幅を計算する方法を説明します。参考のために皆さんと共有してください。詳細は次のとおりです:

私は現在、Python で小さな CLI プログラムを作成しています。これには、文字幅の計算が含まれます。その目的は、長い文字列をわかりやすい方法で同じ幅の断片に分割することです。

Unicode 文字の場合、Python の len 関数はその文字に含まれる文字数を正確に計算できますが、その数値は幅を表しません。

>>>len(u'你好a')
3

したがって、この方法で単純に幅を計算することはできません。

GBK デコード

まずGBKエンコードを考えたのですが、00~7Fまでの文字は半角エンコード、それ以外は文字の幅とほぼ一致する全角エンコードということになりました。この便宜的な方法を使用します (幅 8 を想定):

>>> a = u'hello你好'
>>> b=a.encode('gbk')
>>> try:
...  print b[:8].decode('gbk')
... except:
...  print b[:7].decode('gbk')
...
hello你

コードに示されているように、まず Unicode 文字列を GBK にエンコードし、次に 8 バイトの幅をインターセプトし、GBK を使用してデコードしようとします。デコードが失敗した場合は、1 つ少ない幅をインターセプトし、7 バイトをインターセプトして GBK デコードを使用します。

問題は当初は解決されましたが、欠点は明らかです。第一に、コードは洗練されておらず、試行錯誤的に実行されます。第二に、GBK が表現できる文字は限られており、GBK エンコーディング以外の多数の文字をサポートできません。

East_Asian_Width

長い間さまよった後、Unicode 文字データベース標準には East_Asian_Width 属性があり、次の可能な値があることを偶然発見しました:

# East_Asian_Width (ea)
ea ; A     ; Ambiguous  不确定
ea ; F     ; Fullwidth  全宽
ea ; H     ; Halfwidth  半宽
ea ; N     ; Neutral   中性
ea ; Na    ; Narrow    窄
ea ; W     ; Wide     宽

不確実な A を除いて、F/H/N/Na/W はすべて幅を明確に知ることができます。保守的に A を幅 2 として扱う場合、単一の幅を与えるのは簡単です。文字:

>>> import unicodedata
>>> def chr_width(c):
...  if (unicodedata.east_asian_width(c) in ('F','W','A')):
...   return 2
...  else:
...   return 1
>>> chr_width(u'你')
2
>>> chr_width(u'a')
1

現在は要件を満たしているように見えますが、実際に使用すると、属性 A を持つ文字が見つかることは珍しくありません。最も典型的なのは中国語の二重引用符です:

>>> chr_width(u'”')
2

ほとんどの固定幅フォントでは、中国語の二重引用符は 1 桁の幅しかありません。複数の中国語の二重引用符が並んでいる場合、誤判定の幅が積み重なることで、インターセプト効果が大幅に減少することは間違いありません。最良のアプローチ。

urwid の解決策

urwid は成熟した Python ターミナル UI ライブラリです。テキスト コンテンツを表示するために、curses に基づいた HTML のようなコントロールをパッケージ化しています。この分野で開発が必要な場合は、curses ライブラリを直接使用するのではなく、このライブラリを強くお勧めします。非常に便利なのは、Unicode のテキスト幅インターセプトが非常に正確であることです。非常に驚いたので、テキスト幅計算のコア コードは次のとおりです。

widths = [
  (126,  1), (159,  0), (687,   1), (710,  0), (711,  1),
  (727,  0), (733,  1), (879,   0), (1154, 1), (1161, 0),
  (4347,  1), (4447,  2), (7467,  1), (7521, 0), (8369, 1),
  (8426,  0), (9000,  1), (9002,  2), (11021, 1), (12350, 2),
  (12351, 1), (12438, 2), (12442,  0), (19893, 2), (19967, 1),
  (55203, 2), (63743, 1), (64106,  2), (65039, 1), (65059, 0),
  (65131, 2), (65279, 1), (65376,  2), (65500, 1), (65510, 2),
  (120831, 1), (262141, 2), (1114109, 1),
]
def get_width( o ):
  """Return the screen column width for unicode ordinal o."""
  global widths
  if o == 0xe or o == 0xf:
    return 0
  for num, wid in widths:
    if o <= num:
      return wid
  return 1

コードに示すように、まず Unicode の公式 EastAsianWidth ドキュメントに従って文字幅範囲テーブルを整理し、次に Unicode コードを使用してテーブルを検索します。前の例を使用してテストします:


>>> get_width(ord(u'a'))
1
>>> get_width(ord(u'你'))
2
>>> get_width(ord(u'”'))
1
これは完全に正確で、実際のアプリケーションでは比較的うまく機能します。詳細については、urwid の old_str_util.py ソース コードを参照してください。

Python 関連のコンテンツにさらに興味がある読者は、このサイトの特別トピックをチェックしてください: 「Python 画像操作スキルの概要」、「Python データ構造とアルゴリズムのチュートリアル」、「Python ソケット プログラミング スキルの概要」、「 Python 関数の使用スキルのまとめ」、「Python の文字列操作のスキルのまとめ」、「Python 入門と上級の古典的なチュートリアル」、および「Python ファイルとディレクトリの操作のスキルのまとめ」

この記事が Python プログラミングのすべての人に役立つことを願っています。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。