2012年01月29日

文書内の全数字を算用数字表現: all2int(), str2int()

 文字列の汎用置替えでは画一的なパターンで画一的に処理する為、必ずしも全てが妥当な置替え結果を得れるものではない。このことは、例えば文書中の数字表記で考えて頂ければ判りやすいだろう。
 「領収額 金壱億弐百参万円也」「面積 百弐拾参・四五坪」通常縦書きの契約書類等で用いられる表記方法である。漢数字も大字と言う改竄防止の画数の多い文字が使われている点は単純にdai2num()でも「領収額 金1億2百3万円也」「面積 百2拾3・45坪」の様に置替えて読み易くすること迄は出来る。
 しかし、これら全てを算用数字に一発で置替えようとすると億、万、百、拾と言う位を表す文字の扱いが問題になる。言わばint(u'1億2百3万')で102030000と言う整数値が生成出来る様にする必要が出て来る。それに応えるものが、今回説明するmire.jcode.str2int()関数である。それに前稿のreplaces()関数を絡めれば、「領収額 金102030000円也」「面積 123・45坪」の様に算用数字表記の整数に置替えることが出来る。

 先ずはmire.jcode.str2int()関数のコードは次の通りだ。仕様は標準のint()同様、数字以外の文字を含むと期待する以外の結果を生む可能性がある仕様としている。また例えば百円とか千円と言うと日本では100円とか1000円の意味であり壱が省略されたものとして対処する仕様としている。



def str2int(s
, piriod='.' #小数点:[u'.', u'・', u'٫', u'・']
, comma=',' #桁区切:[u',', u'٬', u',', u' ', u'.', u'、']
):
"""
漢数字、全角数字、半角数字文字列の整数化
【仕様】
1. 拾, 百, 千, 万, 億等が数字の頭にあるときは頭の一が省略されたものと看做す
2. 数字でない余計な文字を含まないこと(現在は、含むと単にpassする)
「、・」等をはさんでいる場合の解釈をどうするか詰めてから対処の予定
"""
#千以下の相対位の刻み
kizami_dic = {u'拾':10
, u'百':100, u'陌':100, u'佰':100
, u'千':1000, u'阡':1000, u'仟':1000}
#万以上の絶対位
kurai_dic = { u'万':10000, u'萬':10000
, u'億':100000000
, u'兆':1000000000000
, u'京':10000000000000000
, u'垓':100000000000000000000
, u'予':1000000000000000000000000
, u'穣':10000000000000000000000000000
, u'溝':100000000000000000000000000000000
, u'潤':1000000000000000000000000000000000000
, u'正':10000000000000000000000000000000000000000}
# 10進数の数字0〜9に当たる全文字に対する整数値の辞書
knum_dic = { '0':0, '1':1, '2':2, '3':3, '4':4
, '5':5, '6':6, '7':7, '8':8, '9':9
, u'0':0, u'1':1, u'2':2, u'3':3, u'4':4
, u'5':5, u'6':6, u'7':7, u'8':8, u'9':9
#漢数字
, u'〇':0, u'一':1, u'二':2, u'三':3, u'四':4
, u'五':5, u'六':6, u'七':7, u'八':8, u'九':9
, u'〇':0, u'壱':1, u'弐':2, u'参':3
#日本の旧大字
, u'零':0, u'壹':1, u'貮':2, u'貳':2, u'參':3
, u'肆':4, u'伍':5, u'陸':6, u'柒':7, u'漆':7
, u'質':7, u'捌':8, u'玖':9
#中国の大字
, u'零':0, u'壹':1, u'贰':2, u'貳':2, u'叁':3, u'參':3
, u'肆':4, u'伍':5, u'陆':6, u'陸':6
, u'柒':7, u'柒':7, u'漆':7, u'捌':8, u'玖':9
#アラビア・インド数字
, u'٠':0, u'١':1 , u'٢':2, u'٣':3, u'٤':4
, u'٥':5, u'٦':6 , u'٧':7, u'٨':8, u'٩':9
#タイ数字
, u'๐':0, u'๑':1, u'๒':2, u'๓':3, u'๔':4
, u'๕':5, u'๖':6, u'๗':7, u'๘':8, u'๙':9
}
r = reverse(s) #末尾文字から解釈するので文字列を反転
ketaage = k3 = k4 = 1 #各桁上げ変数を1に初期化
n = 0 #桁刻みの数の計算用
p = '' #次の処理の為一つ前の文字の区分を記録
for i in r: #末尾より一文字ずつ
if i in knum_dic: # 漢数字0〜9なら
if p=='n': # もし、一つ前もそうなら
ketaage *= 10 # kizamiに依存せず一桁上げ
n += (k3 * k4 * ketaage # 拾百千の桁刻みが省かれているものとして
* knum_dic[i]) # 一桁桁上げして加算
else: # でないなら
n += k3 * k4 * knum_dic[i] # 万以上の位と千以下の刻みをかけて加算
p = 'n' # 次の処理の為一つ前が数字文字だったと記録
elif i in kizami_dic: # 千百十の刻みなら
k3 = kizami_dic[i] # 千以下の刻み桁数を代入: 千=1000, 百=100, 拾=10
ketaage = 1 # 漢数字0〜9連続時の桁上げをクリア
p = 'z' # 次の処理の為一つ前が千以下の刻み文字だったと記録
elif i in kurai_dic: # 万以上の絶対位の文字なら
k4 = kurai_dic[i] # 万以上の絶対位の桁数を代入: 万=10000
k3 = 1 # 千以下の刻み桁数をクリア
ketaage = 1 # 漢数字0〜9連続時の桁上げをクリア
p = 'k' # 次の処理の為一つ前が万以上の位文字だったと記録
else: # それ以外は
print i, u':数字外の文字' # 取り敢えず、画面表示してpassしておく …(2)
if p=='z' or p=='k': #最後の未処理分は
n += k3 * k4 # 頭の一が省略されたものと看做し処理 …(1)
return n #結果を返す

def reverse(s):
"""Unicode文字列用の降順並替関数(python2.x系のunicode型にはreverse()メソッドがない)"""
st = list(s) #いきなりlist化
st.reverse()
return u''.join(st)

 2012-01-29時点のコードでは、print str2int(u'「領収額 金壱億弐百参万円也」「面積 百弐拾参・四五坪」')とするとエラーこそ出ないものの次の様に面積の少数値から連続で桁を合せて加算した奇妙な整数を返すことになる。

[mire@localhost ~]$ python jpcode_0_2_6.py
「領収額 金1億2百3万円也」「面積 百2拾3・45坪」
」 :数字外の文字
坪 :数字外の文字
・ :数字外の文字
:数字外の文字
積 :数字外の文字
面 :数字外の文字
「 :数字外の文字
」 :数字外の文字
也 :数字外の文字
円 :数字外の文字
金 :数字外の文字
:数字外の文字
額 :数字外の文字
収 :数字外の文字
領 :数字外の文字
「 :数字外の文字
102030365

 従って、数字部分のみを、このstr2int()に渡す動作は次のall2int()関数側で行なわねばならない。



def all2int(s, add_chars=u'', del_chars=u''):
"""数を表す全数字を算用数字に置替え"""
from re import compile, findall
all_num = (u'拾百千万億兆京垓予穣溝潤正'
+ u'01234567890123456789〇一二三四五六七八九'
+ u'〇壱弐参零壹貮貳參肆伍陸柒漆質捌玖'
+ u'零壹贰貳叁參肆伍陆陸柒柒漆捌玖')
num_strs = list(set(list(all_num+add_chars)))
for d in del_chars:
num_strs.sremove(d)
num_strs.sort()
are_nums = compile(u'[%s]+' % (u''.join(num_strs)))
nums = are_nums.findall(s)
pat_dic = {}
for i in nums:
pat_dic[i] = u'%d' % (str2int(i))
return replaces(s, pat_dic)
 その仕組みとして、数字に当たる文字を一つ以上含む部分文字列を正規表現モジュールreを使って抽出し、それに対する整数値を文字列化したものを値とする辞書を作成して、それを使い 文字列をreplaces()することで実現している次第だけ。
posted by Mire at 19:39 | Comment(0) | TrackBack(0) | Pythonプログラミング | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
月額見放題1,000円開始キャンペーンバナー(画像ありver)
紺碧の艦隊 ルパン三世 GREAT CHASE クリックプロモーション
<< 2013年01月 >>
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
カテゴリ
タグクラウド
ファン
利用中のオープンソース
最近のコメント
最近の記事
過去ログ
QRコード
レガシーなアプリはいかが?
Dell 法人のお客様ページ
  • 【法人様向け】デル、お得なキャンペーン情報
  • 法人のお客様向け ストレージソリューション
  • 法人のお客様向け ネットワークソリューション
  • 【SOHO法人様向け】デル・オンライン広告限定ページ
  • デル-個人のお客様ページ
  • 【個人のお客様向け】デル・オンライン広告限定ページ
  • オンライン広告限定キャンペーンページ
  • ソフトウェア&周辺機器 パソコン工房
    ツートップインターネットショップ(twotop.co.jp) マウスコンピューター/G-Tune
  • ×

    この広告は1年以上新しい記事の投稿がないブログに表示されております。