将逗号插入数字string
嘿,我试图在一个string上执行一个向后的正则expression式search,把它分成3个数字组。 就我从AS3 文档中可以看到,向后search在reg ex引擎中是不可能的。
这个练习的要点是把三连词的逗号插入一个数字,如下所示:
10000000 => 10,000,000
我正在考虑这样做:
string.replace(/(\d{3})/g, ",$1")
但是由于search没有发生在后面,所以这是不正确的,replace$ 1将只能用于第一场比赛。
我感觉我会更好地使用循环执行此任务。
更新:
由于AS3不支持lookahead这是我已经解决了它。
public static function formatNumber(number:Number):String { var numString:String = number.toString() var result:String = '' while (numString.length > 3) { var chunk:String = numString.substr(-3) numString = numString.substr(0, numString.length - 3) result = ',' + chunk + result } if (numString.length > 0) { result = numString + result } return result }
如果你的语言支持postive lookahead断言,那么我认为下面的正则expression式将工作:
(\d)(?=(\d{3})+$)
在Java中演示:
import static org.junit.Assert.assertEquals; import org.junit.Test; public class CommifyTest { @Test public void testCommify() { String num0 = "1"; String num1 = "123456"; String num2 = "1234567"; String num3 = "12345678"; String num4 = "123456789"; String regex = "(\\d)(?=(\\d{3})+$)"; assertEquals("1", num0.replaceAll(regex, "$1,")); assertEquals("123,456", num1.replaceAll(regex, "$1,")); assertEquals("1,234,567", num2.replaceAll(regex, "$1,")); assertEquals("12,345,678", num3.replaceAll(regex, "$1,")); assertEquals("123,456,789", num4.replaceAll(regex, "$1,")); } }
以下链接build议AS3呢?
在http://gskinner.com/RegExr/find
社区>千位分隔符
模式: /\d{1,3}(?=(\d{3})+(?!\d))/g
replace: $&,
trace ( String("1000000000").replace( /\d{1,3}(?=(\d{3})+(?!\d))/g , "$&,") );
它完成了这项工作!
如果您的正则expression式引擎具有积极的lookahead,你可以做这样的事情:
string.replace(/(\d)(?=(\d\d\d)+$)/, "$1,")
如果正向超前(?= …)意味着正则expression式只在超前expression式匹配时才匹配。
(请注意,lookaroundexpression式并不总是非常有效。)
虽然这些答案中的许多答案正确的整数工作正常,他们的许多参数input被转换为数字,这意味着他们可以处理负值或包含小数,在这里所有的解决scheme失败。 虽然目前select的答案并不假设一个数字,我很想find一个解决scheme,可以和比RegExp更高性能(AS3不好)。
我在testing课上把许多答案放在一起(包括一个来自这个博客的解决scheme和一个我自己称之为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; } } }
然后我testing每个准确性和性能:
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: .012345, output: "0.012345" }, { input: 1.012345, output: "1.012345" }, { input: 21.012345, output: "21.012345" }, { input: 321.012345, output: "321.012345" }, { input: 4321.012345, output: "4,321.012345" }, { input: 54321.012345, output: "54,321.012345" }, { input: 654321.012345, output: "654,321.012345" }, { input: 7654321.012345, output: "7,654,321.012345" }, { input: 987654321.012345, output: "987,654,321.012345" }, { input: 1987654321.012345, output: "1,987,654,321.012345" }, { input: 21987654321.012345, output: "21,987,654,321.012345" }, { input: -.012345, output: "-0.012345" }, { input: -1.012345, output: "-1.012345" }, { input: -21.012345, output: "-21.012345" }, { input: -321.012345, output: "-321.012345" }, { input: -4321.012345, output: "-4,321.012345" }, { input: -54321.012345, output: "-54,321.012345" }, { input: -654321.012345, output: "-654,321.012345" }, { input: -7654321.012345, output: "-7,654,321.012345" }, { input: -987654321.012345, output: "-987,654,321.012345" }, { input: -1987654321.012345, output: "-1,987,654,321.012345" }, { input: -21987654321.012345, output: "-21,987,654,321.012345" } ]; 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 = of; 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 = of; 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缺less更大数字的精度,所以每个class级都没有通过这些testing:
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.012344 !== 21,987,654,321.012345 Test #53 Failed: -21,987,654,321.012344 !== -21,987,654,321.012345
但只有两个函数通过了所有其他testing: commaify()和addCommas() 。
性能testing表明, commaify()是所有解决scheme中最重要的:
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()满足多function性和性能的要求,尽pipe当然不是最紧凑或优雅。
这真的不是RegEx的最佳使用…我不知道数字格式化函数,但这个线程似乎提供了一个解决scheme。
function commaCoder(yourNum):String { //var yourNum:Number = new Number(); var numtoString:String = new String(); var numLength:Number = yourNum.toString().length; numtoString = ""; for (i=0; i<numLength; i++) { if ((numLength-i)%3 == 0 && i != 0) { numtoString += ","; } numtoString += yourNum.toString().charAt(i); trace(numtoString); } return numtoString; }
如果您确实坚持使用RegEx,则可以反转string,应用RegExreplace函数,然后将其撤回。
一个sexeger对此很有帮助 。 简而言之,一个sexeger是一个颠倒的正则expression式,反向的string反转了输出。 它通常比替代方法更有效率。 这是你想要做的一些伪代码:
string = reverse string string.replace(/(\d{3})(?!$)/g, "$1,") string = reverse string
这是一个Perl实现
#!/usr/bin/perl use strict; use warnings; my $s = 13_456_789; for my $n (1, 12, 123, 1234, 12345, 123456, 1234567) { my $s = reverse $n; $s =~ s/([0-9]{3})(?!$)/$1,/g; $s = reverse $s; print "$s\n"; }
你可能要考虑NumberFormatter
//这是一个简单的代码,它工作正常… 🙂
import java.util.Scanner; public class NumberWithCommas { public static void main(String a[]) { Scanner sc = new Scanner(System.in); String num; System.out.println("\n enter the number:"); num = sc.next(); printNumber(num); } public static void printNumber(String ar) { int len, i = 0, temp = 0; len = ar.length(); temp = len / 3; if (len % 3 == 0) temp = temp - 1; len = len + temp; char[] ch = ar.toCharArray(); char[] ch1 = new char[len]; for (int j = 0, k = (ar.length() - 1); j < len; j++) { if (i < 3) { ch1[j] = ch[k]; i++; k--; } else { ch1[j] = ','; i = 0; } } for (int j = len - 1; j >= 0; j--) System.out.print(ch1[j]); System.out.println(""); } }
试试这个代码。 这是简单和最好的性能。
var reg:RegExp=/\d{1,3}(?=(\d{3})+(?!\d))/g; var my_num:Number = 48712694; var my_num_str:String = String(my_num).replace(reg,"$&,"); trace(my_num_str);
::输出::
48,712,694