2009/05/20
数字を3桁区切りで表示するJavaScript
最近、業務でJavaScriptを使っていますが、数字を3桁区切りで表現する関数が元々JavaScriptにないことを知りました。
こんなものがないのか、とびっくりしましたが、とりあえず考えて作るより検索した方が早いと思ったので、Googleで検索するとこちらにありました。
これです。ちょっと感動しました。エッセンスはwhileのある1行。考えた人はすごいですね。
たった1行でできてしまうんですから。
半ば備忘録になりますが、少し説明しておきます。
まず、var numの行。これは与えられた文字列strに元々カンマがある場合、そのカンマを外しておく処理です。カンマを外したものがnumに返ります。
問題のwhileの行ですが、まず正規表現/^(-?\d+)(\d{3})/を検討してみます。
^ :文字列の先頭という意味。
-? :マイナス文字が0個か1個という意味。数字の符号のマイナスのことです。
\d+ :0~9の10進数文字が1個以上という意味。
\d{3} :0~9の10進数文字が3個という意味。
よって、正規表現/^(-?\d+)(\d{3})/は「文字列の先頭からマイナス文字がないか、もしくは1個だけあり、そのあとに0~9の数字が1個以上続き、さらに0~9の数字が3個ある」ということです。
例を挙げてみます。num = "1234567.8901"だとします。
「0~9の数字が1個以上続き、さらに0~9の数字が3個ある」は、パターンとして
1 と 234
12 と 345
123 と 456
1234 と 567
の4通りありますが、正規表現の文字列マッチは最長のものになりますので(これをgreedy、貪欲なマッチといいます)、この場合は1234 と 567です。
カッコがついているので、1234が$1に、567が$2になります。したがってwhileの1回目のループで
num.replace((/^(-?\d+)(\d{3})/, "$1,$2")) は 1234,567.8901
になります。これがnumに代入され(1234,567.8901)、元々のnum(1234567.8901)と比較すると、文字列として異なります。したがって2回目のループに入ります。以下、わかりやすいようにループごとのnumの中身を書いてみますと、
左辺 比較 右辺
1234567.8901 != 1234,567.8901 1回目
1234,567.8901 != 1,234,567.8901 2回目
1,234,567.8901 == 1,234,567.8901 3回目
となって、3回目のループに入る前に終了します。
この複雑な処理が、実質1行で実現しているわけですから、本当にすごいscriptです。
ちなみにGoogle検索すると、他にも3桁区切りを行うscriptが紹介されていましたが、何十行にもわたるものであったり、中にはそのままコピー・ペーストしてもエラーになるものもありました。このscriptが最高だと思います。
なお、このscriptでは例えば、
+12345のように、プラス記号が先頭にある数字
0012345のように、ゼロサプレスしていない数字
だときれいな3桁区切りにしてくれませんが、それを考慮するscriptを作るのは、このwhileのある1行に比べればはるかに簡単です。
とにかくこの情報で大変助かりました。今日ではwebに接続できない環境での開発は考えられません。
こんなものがないのか、とびっくりしましたが、とりあえず考えて作るより検索した方が早いと思ったので、Googleで検索するとこちらにありました。
function addFigure(str) {
var num = new String(str).replace(/,/g, "");
while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2")));
return num;
}
これです。ちょっと感動しました。エッセンスはwhileのある1行。考えた人はすごいですね。
たった1行でできてしまうんですから。
半ば備忘録になりますが、少し説明しておきます。
まず、var numの行。これは与えられた文字列strに元々カンマがある場合、そのカンマを外しておく処理です。カンマを外したものがnumに返ります。
問題のwhileの行ですが、まず正規表現/^(-?\d+)(\d{3})/を検討してみます。
^ :文字列の先頭という意味。
-? :マイナス文字が0個か1個という意味。数字の符号のマイナスのことです。
\d+ :0~9の10進数文字が1個以上という意味。
\d{3} :0~9の10進数文字が3個という意味。
よって、正規表現/^(-?\d+)(\d{3})/は「文字列の先頭からマイナス文字がないか、もしくは1個だけあり、そのあとに0~9の数字が1個以上続き、さらに0~9の数字が3個ある」ということです。
例を挙げてみます。num = "1234567.8901"だとします。
「0~9の数字が1個以上続き、さらに0~9の数字が3個ある」は、パターンとして
1 と 234
12 と 345
123 と 456
1234 と 567
の4通りありますが、正規表現の文字列マッチは最長のものになりますので(これをgreedy、貪欲なマッチといいます)、この場合は1234 と 567です。
カッコがついているので、1234が$1に、567が$2になります。したがってwhileの1回目のループで
num.replace((/^(-?\d+)(\d{3})/, "$1,$2")) は 1234,567.8901
になります。これがnumに代入され(1234,567.8901)、元々のnum(1234567.8901)と比較すると、文字列として異なります。したがって2回目のループに入ります。以下、わかりやすいようにループごとのnumの中身を書いてみますと、
左辺 比較 右辺
1234567.8901 != 1234,567.8901 1回目
1234,567.8901 != 1,234,567.8901 2回目
1,234,567.8901 == 1,234,567.8901 3回目
となって、3回目のループに入る前に終了します。
この複雑な処理が、実質1行で実現しているわけですから、本当にすごいscriptです。
ちなみにGoogle検索すると、他にも3桁区切りを行うscriptが紹介されていましたが、何十行にもわたるものであったり、中にはそのままコピー・ペーストしてもエラーになるものもありました。このscriptが最高だと思います。
なお、このscriptでは例えば、
+12345のように、プラス記号が先頭にある数字
0012345のように、ゼロサプレスしていない数字
だときれいな3桁区切りにしてくれませんが、それを考慮するscriptを作るのは、このwhileのある1行に比べればはるかに簡単です。
とにかくこの情報で大変助かりました。今日ではwebに接続できない環境での開発は考えられません。
スポンサーサイト
コメント
すげー便利です
ありがとうございます
ありがとうございます
コメントありがとうございます。
お役に立てて幸いです。
今後とも、よろしくお願いします。
お役に立てて幸いです。
今後とも、よろしくお願いします。
コメントの投稿
トラックバック
トラックバックURL:http://sookibizviz.blog81.fc2.com/tb.php/100-97358be5