Хотя многие из этих ответов отлично работают с положительными целыми числами, многие из их аргументов входов отлиты в цифрах, что подразумевает что они могут обрабатывать отрицательные значения или содержать десятичные числа, и здесь все решения терпят неудачу. Хотя выбранный в данный момент ответ не принимает номер, мне было любопытно найти решение, которое могло бы и было бы более эффективным, чем RegExp (какой AS3 не подходит).
я собрал много ответов здесь, в классе тестирования (и включал решение от этого blog и ответ моего собственного названного commaify) и отформатированы их последовательным образом для легкого сравнения:
package
{
public class CommaNumberSolutions
{
public static function commaify(input:Number):String
{
var split:Array = input.toString().split('.'),
front:String = split[0],
back:String = (split.length > 1) ? "." + split[1] : null,
n:int = input < 0 ? 2 : 1,
commas:int = Math.floor((front.length - n)/3),
i:int = 1;
for (; i <= commas; i++)
{
n = front.length - (3 * i + i - 1);
front = front.slice(0, n) + "," + front.slice(n);
}
if (back)
return front + back;
else
return front;
}
public static function getCommaString(input:Number):String
{
var s:String = input.toString();
if (s.length <= 3)
return s;
var i:int = s.length % 3;
if (i == 0)
i = 3;
for (; i < s.length; i += 4)
{
var part1:String = s.substr(0, i);
var part2:String = s.substr(i, s.length);
s = part1.concat(",", part2);
}
return s;
}
public static function formatNumber(input:Number):String
{
var s:String = input.toString()
var result:String = ''
while (s.length > 3)
{
var chunk:String = s.substr(-3)
s = s.substr(0, s.length - 3)
result = ',' + chunk + result
}
if (s.length > 0)
result = s + result
return result
}
public static function commaCoder(input:Number):String
{
var s:String = "";
var len:Number = input.toString().length;
for (var i:int = 0; i < len; i++)
{
if ((len-i) % 3 == 0 && i != 0)
s += ",";
s += input.toString().charAt(i);
}
return s;
}
public static function regex1(input:Number):String
{
return input.toString().replace(/-{0,1}(\d)(?=(\d\d\d)+$)/g, "$1,");
}
public static function regex2(input:Number):String
{
return input.toString().replace(/-{0,1}\d{1,3}(?=(\d{3})+(?!\d))/g , "$&,")
}
public static function addCommas(input:Number):String
{
var negative:String = "";
if (input < 0)
{
negative = "-";
input = Math.abs(input);
}
var s:String = input.toString();
var results:Array = s.split(/\./);
s = results[0];
if (s.length > 3)
{
var mod:Number = s.length % 3;
var output:String = s.substr(0, mod);
for (var i:Number = mod; i < s.length; i += 3)
{
output += ((mod == 0 && i == 0) ? "" : ",") + s.substr(i, 3);
}
if (results.length > 1)
{
if (results[1].length == 1)
return negative + output + "." + results[1] + "0";
else
return negative + output + "." + results[1];
}
else
return negative + output;
}
if (results.length > 1)
{
if (results[1].length == 1)
return negative + s + "." + results[1] + "0";
else
return negative + s + "." + results[1];
}
else
return negative + s;
}
}
}
Затем я проверил каждый для точности и производительности:
package
{
public class TestCommaNumberSolutions
{
private var functions:Array;
function TestCommaNumberSolutions()
{
functions = [
{ name: "commaify()", f: CommaNumberSolutions.commaify },
{ name: "addCommas()", f: CommaNumberSolutions.addCommas },
{ name: "getCommaString()", f: CommaNumberSolutions.getCommaString },
{ name: "formatNumber()", f: CommaNumberSolutions.formatNumber },
{ name: "regex1()", f: CommaNumberSolutions.regex1 },
{ name: "regex2()", f: CommaNumberSolutions.regex2 },
{ name: "commaCoder()", f: CommaNumberSolutions.commaCoder }
];
verify();
measure();
}
protected function verify():void
{
var assertions:Array = [
{ input: 1, output: "1" },
{ input: 21, output: "21" },
{ input: 321, output: "321" },
{ input: 4321, output: "4,321" },
{ input: 54321, output: "54,321" },
{ input: 654321, output: "654,321" },
{ input: 7654321, output: "7,654,321" },
{ input: 987654321, output: "987,654,321" },
{ input: 1987654321, output: "1,987,654,321" },
{ input: 21987654321, output: "21,987,654,321" },
{ input: 321987654321, output: "321,987,654,321" },
{ input: 4321987654321, output: "4,321,987,654,321" },
{ input: 54321987654321, output: "54,321,987,654,321" },
{ input: 654321987654321, output: "654,321,987,654,321" },
{ input: 7654321987654321, output: "7,654,321,987,654,321" },
{ input: 87654321987654321, output: "87,654,321,987,654,321" },
{ input: -1, output: "-1" },
{ input: -21, output: "-21" },
{ input: -321, output: "-321" },
{ input: -4321, output: "-4,321" },
{ input: -54321, output: "-54,321" },
{ input: -654321, output: "-654,321" },
{ input: -7654321, output: "-7,654,321" },
{ input: -987654321, output: "-987,654,321" },
{ input: -1987654321, output: "-1,987,654,321" },
{ input: -21987654321, output: "-21,987,654,321" },
{ input: -321987654321, output: "-321,987,654,321" },
{ input: -4321987654321, output: "-4,321,987,654,321" },
{ input: -54321987654321, output: "-54,321,987,654,321" },
{ input: -654321987654321, output: "-654,321,987,654,321" },
{ input: -7654321987654321, output: "-7,654,321,987,654,321" },
{ input: -87654321987654321, output: "-87,654,321,987,654,321" },
{ input: ., output: "0." },
{ input: 1., output: "1." },
{ input: 21., output: "21." },
{ input: 321., output: "321." },
{ input: 4321., output: "4,321." },
{ input: 54321., output: "54,321." },
{ input: 654321., output: "654,321." },
{ input: 7654321., output: "7,654,321." },
{ input: 987654321., output: "987,654,321." },
{ input: 1987654321., output: "1,987,654,321." },
{ input: 21987654321., output: "21,987,654,321." },
{ input: -., output: "-0." },
{ input: -1., output: "-1." },
{ input: -21., output: "-21." },
{ input: -321., output: "-321." },
{ input: -4321., output: "-4,321." },
{ input: -54321., output: "-54,321." },
{ input: -654321., output: "-654,321." },
{ input: -7654321., output: "-7,654,321." },
{ input: -987654321., output: "-987,654,321." },
{ input: -1987654321., output: "-1,987,654,321." },
{ input: -21987654321., output: "-21,987,654,321." }
];
var i:int;
var len:int = assertions.length;
var assertion:Object;
var f:Function;
var s1:String;
var s2:String;
for each (var o:Object in functions)
{
i = 0;
f = o.f;
trace('\rVerify: ' + o.name);
for (; i < len; i++)
{
assertion = assertions[ i ];
s1 = f.apply(null, [ assertion.input ]);
s2 = assertion.output;
if (s1 !== s2)
trace('Test #' + i + ' Failed: ' + s1 + ' !== ' + s2);
}
}
}
protected function measure():void
{
// Generate random inputs
var values:Array = [];
for (var i:int = 0; i < 999999; i++) {
values.push(Math.random() * int.MAX_VALUE * (Math.random() > .5 ? -1 : 1));
}
var len:int = values.length;
var stopwatch:Stopwatch = new Stopwatch;
var s:String;
var f:Function;
trace('\rTesting ' + len + ' random values');
// Test each function
for each (var o:Object in functions)
{
i = 0;
s = "";
f = o.f;
stopwatch.start();
for (; i < len; i++) {
s += f.apply(null, [ values[i] ]) + " ";
}
stopwatch.stop();
trace(o.name + '\t\ttook ' + (stopwatch.elapsed/1000) + 's'); //(stopwatch.elapsed/len) + 'ms'
}
}
}
}
import flash.utils.getTimer;
class Stopwatch
{
protected var startStamp:int;
protected var stopStamp:int;
protected var _started:Boolean;
protected var _stopped:Boolean;
function Stopwatch(startNow:Boolean = true):void
{
if (startNow)
start();
}
public function start():void
{
startStamp = getTimer();
_started = true;
_stopped = false;
}
public function stop():void
{
stopStamp = getTimer();
_stopped = true;
_started = false;
}
public function get elapsed():int
{
return (_stopped) ? stopStamp - startStamp : (_started) ? getTimer() - startStamp : 0;
}
public function get started():Boolean
{
return _started;
}
public function get stopped():Boolean
{
return _stopped;
}
}
из-за отсутствия AS3 в точности с большими числами каждый класс неудавшейся эти тесты:
Test #15 Failed: 87,654,321,987,654,320 !== 87,654,321,987,654,321
Test #31 Failed: -87,654,321,987,654,320 !== -87,654,321,987,654,321
Test #42 Failed: 21,987,654,321.!== 21,987,654,321.
Test #53 Failed: -21,987,654,321.!== -21,987,654,321.
Но только две функции прошли все другие тесты: commaify() и addCommas().
тесты производительности показывают, что commaify() является наиболее preformant всех решений:
Testing 999999 random values
commaify() took 12.411s
addCommas() took 17.863s
getCommaString() took 18.519s
formatNumber() took 14.409s
regex1() took 40.654s
regex2() took 36.985s
Кроме commaify() может быть расширен до включая аргументы для десятичного длины и нулевого заполнения на десятичной часть - она также превосходит другие по 13.128s:
public static function cappedDecimal(input:Number, decimalPlaces:int = 2):Number
{
if (decimalPlaces == 0)
return Math.floor(input);
var decimalFactor:Number = Math.pow(10, decimalPlaces);
return Math.floor(input * decimalFactor)/decimalFactor;
}
public static function cappedDecimalString(input:Number, decimalPlaces:int = 2, padZeros:Boolean = true):String
{
if (padZeros)
return cappedDecimal(input, decimalPlaces).toFixed(decimalPlaces);
else
return cappedDecimal(input, decimalPlaces).toString();
}
public static function commaifyExtended(input:Number, decimalPlaces:int = 2, padZeros:Boolean = true):String
{
var split:Array = cappedDecimalString(input, decimalPlaces, padZeros).split('.'),
front:String = split[0],
back:String = (split.length > 1) ? "." + split[1] : null,
n:int = input < 0 ? 2 : 1,
commas:int = Math.floor((front.length - n)/3),
i:int = 1;
for (; i <= commas; i++)
{
n = front.length - (3 * i + i - 1);
front = front.slice(0, n) + "," + front.slice(n);
}
if (back)
return front + back;
else
return front;
}
Так что, я бы предложил, что commaify() отвечает требованиям универсальности и за форма, хотя, конечно, не самая компактная или элегантная.
По вашей ссылке, AS3 делает поддержку lookaheads. Найдите раздел по группам. – toolkit
действительно? Хм пропустил это. Я посмотрю Спасибо. –
Некоторый код, который очень хорошо работает для меня, размещен здесь http://www.cgiinteractive.com/blog/2009/05/formatting-numbers-with-commas-in-as3/ – jln646v