ActionScript3で、数字3桁ごとにコンマを打つ正規表現について
http://q.hatena.ne.jp/1238501061
数分前にエントリーした質問です。もしよろしければこちらも合わせてお願いします。
・3桁ごとにコンマを打ちたい
・ただし、小数点以下にはつけない
num.toString().replace( /([0-9]+?)(?=(?:[0-9]{3})+$)/g , ‘$1,’ );
・上記だと小数点以下にコンマが付いてしまいます。
置換前)1234567899.987654321
置換後)1234567899.98,765,433
理想)1,234,567,899.98765433;
できれば、「違う」とかいう単純な回答や、コードや参考URLを提示するだけではなく、解説をお願いします。もちろん、勉強したいので参考URL大歓迎です。
よろしくお願いします。
参考サイト
JavaScriptで数字3桁ごとにコンマを打つ
http://logic.stepserver.jp/data/archives/440.html
/([0-9]+?)(?=([0-9]{3})+([^0-9]))/g , '$1,'
質問にあった "(?=([0-9]{3})+$)" は、右側に数字 [0-9] が3つ連続して {3} 文字列の末尾 $ になるパターンにマッチします。たとえば、"1234567899" であれば、"899" にマッチします。
ところが、"1234567899.987654321" ですと、文字列の末尾の "321" がマッチしますが、これは少数以下です。
そこで、"$" の代わりに "[^0-9]" を置いて、数字以外の文字にマッチするようにしました。これであれば、"1234567899.987654321" の "899.987654321" がマッチすることになるので、小数点以下の部分にはカンマは付きません。
ただし、"$" を除いてしまったので、"1234567899" にはカンマが付かなくなります。
"1234567899." としていただくか、数字の最後に空白文字や改行文字を付けてください。
コメントが無効でしたので、回答で失礼します。
今回のケースでは、末尾を小数点か行末という判断にすればよいのですから、
$ を [$\.] に変えれば、小数までの変換となります。ですから
num.toString().replace( /([0-9]+?)(?=(?:[0-9]{3})+[$\.])/g,'$1,');
とすることで、両方に対応できるかと思います。
ご回答ありがとうございます。
コメントの有効・無効ができたんですね。知りませんでした。(汗
これは!と思って早速試してみたところ、小数点ではうまくいったのですが、整数だけだとコンマが付与されませんでした。[]内に$って効かなかったりするんですかねぇ・・・。¥.は効いてるから、[]自体が意味がないというわけではないと思うのですが・・・。あるいは$を[]内に書く場合にエスケープ文字をつけるような、何かしらルールがあるとか・・・。
うーん。こういうちょっとした追加で出来るならそれが一番いいんですが・・・。
var num:Number = 123456789;
trace(num);
trace(num.toString().replace( /([0-9]+?)(?=(?:[0-9]{3})+[$\.])/g,'$1,'));
結果
123456789
123456789
========================
var num:Number = 123456789.987654;
trace(num);
trace(num.toString().replace( /([0-9]+?)(?=(?:[0-9]{3})+[$\.])/g,'$1,'));
結果
123456789.987654
123,456,789.987654
ActionScriptは分からないのですが、
多分JavaScriptと同様にできると思いますので、参考までに。
replaceの第二引数には関数が設定できます。
http://livedocs.adobe.com/flash/9.0_jp/ActionScriptLangRefV3/Str...
のreplaceメソッドを参照してください。
以下はJavaScriptの例。
alert("123456789.9987654321".replace(/^([0-9]+)(?=\.|$)/, function(){ return arguments[1].replace(/([0-9]+?)(?=(?:[0-9]{3})+$)/g, '$1,'); }));
1回「最初から数字の連続で"."直前までか最後までの文字列」を取得して、その文字列を3桁区切りでカンマを入れてます。
第二引数の関数には、実行時、引数の1番目に一致文字列全体、2番目以降にキャプチャ文字列が順に入ります。
関数が返却した文字列により、元の文字列の一致部分が置き換わります。
これなら文字列に「.」がなくても対応できます。
gオプションはここでは使ってませんが、併用すると絶大な効果を発揮する場合があります。
ちょっと高度ですが。(最初聞いたとき私もよく分からなかった・・・。)
C#でも同様の機構があるので、覚えておいて損はないです。
こちらでもご回答ありがとうございます。(笑
動作確認したところ、両方ばっちりでした。あちらでのご回答でだいぶ頭もこなれてきたらしく、なんとか読める感じになったみたいです。まだ読めるだけで、思い浮かぶかは微妙なところですけれど。
replaceの第2引数に関数が使えるっていうのは初めて知りました。ヘルプにも書いてありますね。arrayのsortメソッドにおける比較関数みたいなものでしょうか。引数が若干厄介というかわかりづらいみたいですけど、確かにこれを使えればreplaceの使用用途や可能性がずいぶん広がりますね。勉強する価値がずいぶんありそうです。
勉強になりました。ありがとうございます。
一応、もう少しだけ回答を募集しておきます。こんな感じでもできるよ、という回答がありましたら是非お願いいたします。
まず最初にお詫びを。「1234567899.987654321」ってFlashCS3で確かめたら小数点以下の桁数オーバーしてました。(汗
イメージということでひとつよろしくお願いします。
早速のご回答ありがとうございます。
"[^0-9]"は最初何で行頭って思ってしまいましたが、[]の中で使うと否定形の意味にもなるんですね。便利というかややこしいというか。
動作も確認できました。ありがとうございます。うーん、奥が深いですねぇ・・・。