2013/07/25

ゼロパディングについてすこし

連番画像の番号なんかは、「桁をそろえる」のを主な目的として
数値よりも先頭側(左側)をゼロで埋めたりします。
↓こういうやつですね

picture.1.tif 〜 picture.1000.tif

picture.0001.tif 〜 picture.1000.tif


前者は、番号 1 のときと、1000のときで、桁数が違います。
となるとファイル名の文字数も違ってきたりして、文字列処理のときとかに都合悪そうです。
一方後者では、番号 1 でも、足りない桁をゼロで埋めることで1000のときと比べても字数に違いが無く、機械的に処理するのに都合が良さそうです。
こういうのを「ゼロパディング」と言います。
「padding」は、pad =「当て物」「詰め物」をする、という意味で、
たとえばHTMLでも隙間を設けるときにpaddingというパラメータを扱ったりしますね。

今回はこのゼロパディングについて、少々。


ちなみにお恥ずかしながら最近知ったんですが、
この「ゼロパディング」、別の呼び方で「ゼロフィル」とも言うそうですね。
なるほど、「fill」だと、ゼロで満たすって感じがしてなんか分かり易いです。

さておき。

単純な文字列処理で、まずはゼロパディングを実現してみたいと思います。

よくある考え方だと、
・先頭側に必要なだけゼロを追加。
・末尾側から必要な桁分取得
…みたいな手順でパディングされた数を得たりするようです。
この考え方で作業を進めてみます。

まずゼロを必要なだけ並べてみます。
例えばこんな風に書いてみたりとか。

zero = ''
while len(zero) <4:
    zero+='0'

というか
zero = '0' * 4
これでいんですね。えへ。

ちなみに最大でゼロがどれだけ必要かですが、
どんな桁数でそろえたいと思っても、最低一桁分は、実際の数値で埋まるので、
ゼロは、最も多くてもそれを差し引いた桁数で充分です。
「四桁で」そろえたければ、ゼロは最大三つ、「五桁」なら最大四つ。
「(必要な桁数 - 1)桁」分、ゼロを用意すれば良さそうです。


ならべたゼロを元になる数値とドッキングして、末尾側から必要な桁分だけ取得します。

x= 1
paddedNum = (zero + x)[-4:]

……ところがこれだとエラーになります。
TypeError(型に関してのエラー)です。 
ここでは変数 zero は文字列型で、変数 x が int型 なので
文字列結合できないよーというわけです。
 仕方ないのでstrに変換して差し上げましょう。

x= 1
paddedNum = (zero + str(x))[-4:]

これで、xにいれる数値がなんであっても、ゼロで桁がそろえられた状態になります。
それとなく関数化↓

def myPadding(x,length):
    zero = '0'*length
    return (zero + str(x))[-length:]

例えばこんな風に使います。

myPadding(123,4)

引数 x はint型に限りません。strを入れても、ゼロパディングしてくれます。

またこうしたアプローチの他にゼロパディングする方法として、
文字列フォーマット操作を用いたものもあるようです。

'%(x)04d'%{'x':1}


非常にコンパクト!
ただ、桁数指定がしづらいかも、みたいなことを思わないでもありません。
あとちょっと抽象度が高すぎるよとか(笑?

……さて。
そんなこんなでゼロパディングです、おつかれさまでーす
って感じなんですが、
それというのも、python に、なんか「padding()」みたいな関数が見当たら無いせいなんですよね。ありそうなんですけどね。

ありそうなんですけどね。

すでに多くの方はこの話しの行く末がお分かりかと思いますが、
「ありそうなんですけど」っていうか、
なににつけても「自分がゼロフィルという言い方を最近知った」ということに尽きます。
なんせ「python padding」で調べてもイマイチどんぴしゃりのが出なかった気がするんです。(いま調べたら見つかるので、検索リテラシーが(後略  というか公式の「文字列メソッド」のとこをよく読m(ry)

ともあれ、「へー ゼロフィルとも言うんだー」とかいいながら
その方向で検索したら、
ちゃんと出てくるんですね!!
pythonにはそれ用のメソッドが、もとから用意されていたわけです。
自分でパディング用の関数なんて作る必要なかったっていうあれです。

それが、こちら

'123'.zfill(4)

文字列メソッド「zfill()」です。
狙いの数値を文字列として用意してそこから呪文を詠唱します。
引数には、桁数を与えます。
注意点として、文字列メソッドなので、数値には使えません。
ということで、
123.zfill(4)


これはいやがられます。 intにそんなメソッドねぇよって壁ドンされます。

ほかにも、ゼロじゃないけどスペースとか好きな文字で埋めたりする系シリーズ「cernter」「rjust」「ljust」がいたりして、
深いよ文字列メソッド。


「ゼロフィルって言うんだー」と思わせておいてzerofillではない辺りにも粋を感じます。
粋すぎて夜も眠れません。




■参考リンク

7.1 ファンシーな出力の書式化 @Python ライブラリリファレンス
http://docs.python.jp/2.4/tut/node9.html#SECTION009100000000000000000

3.6.1 文字列メソッド @Python ライブラリリファレンス
http://docs.python.jp/2.5/lib/string-methods.html

3.6.2 文字列フォーマット操作 @Python ライブラリリファレンス
http://docs.python.jp/2.5/lib/typesseq-strings.html

スライスを使った部分リストの取得 @PythonWeb
http://www.pythonweb.jp/tutorial/list/index3.html


0 件のコメント:

コメントを投稿