将逗号插入数字字符串

时间:2009-04-06 12:55:25

标签: regex actionscript-3

嘿那里,我正在尝试对字符串执行向后正则表达式搜索,将其划分为3位数组。据我所知,从AS3 documentation可以看到,在reg ex引擎中无法向后搜索。

本练习的目的是将三联体逗号插入如下数字中:

10000000 => 10,000,000

我正在考虑这样做:

string.replace(/(\d{3})/g, ",$1")

但这不正确,因为搜索没有从后面发生,替换$ 1只适用于第一场比赛。

我感觉我会更好地使用循环执行此任务。

更新:

由于AS3不支持前瞻,这就是我解决它的方法。

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
}

12 个答案:

答案 0 :(得分:47)

如果您的语言支持正面预测断言,那么我认为以下正则表达式将起作用:

(\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,"));    
    }    
}

以下link建议AS3做什么?

答案 1 :(得分:16)

http://gskinner.com/RegExr/

上找到

社区>数千个分隔符

模式:/\d{1,3}(?=(\d{3})+(?!\d))/g

替换:$&,

trace ( String("1000000000").replace( /\d{1,3}(?=(\d{3})+(?!\d))/g , "$&,") );

完成了这项工作!

答案 2 :(得分:9)

如果您的正则表达式引擎具有正向前瞻,您可以执行以下操作:

string.replace(/(\d)(?=(\d\d\d)+$)/, "$1,")

正向前瞻(?= ...)意味着正则表达式仅在前瞻表达式匹配时匹配。

(注意,环绕表达式并不总是非常有效。)

答案 3 :(得分:4)

虽然许多这些答案在正整数下工作正常,但许多参数输入都被转换为数字,这意味着它们可以处理负值或包含小数,这里所有解决方案都失败了。虽然目前选择的答案并没有假设一个数字,但我很想找到一个能够比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: .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 = 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.012344 !== 21,987,654,321.012345
Test #53 Failed: -21,987,654,321.012344 !== -21,987,654,321.012345

但只有两个函数通过了所有其他测试: commaify() addCommas()

性能测试表明 commaify()是所有解决方案中最具代表性的:

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()满足多功能性和性能的要求,但肯定不是最紧凑或优雅的。

答案 4 :(得分:2)

这真的不是RegEx的最佳用法......我不知道数字格式化功能,但this thread似乎提供了解决方案。

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,你可以反转字符串,应用RegEx替换功能,然后将其反转。

答案 5 :(得分:2)

sexeger对此有好处。简而言之,一个性别者是一个反向的正则表达式运行反对一个反转的字符串,你扭转了输出。它通常比替代方案更有效。以下是您想要做的一些伪代码:

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";
}

答案 6 :(得分:1)

您可能需要考虑NumberFormatter

答案 7 :(得分:0)

//这是一个简单的代码,它工作正常......:)

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("");
    }
}

答案 8 :(得分:0)

如果您无法在正则表达式上使用前瞻,则可以使用:

string.replace(/^(.*?,)?(\d{1,3})((?:\d{3})+)$/, "$1$2,$3")

在循环内部,直到没有什么可以替换。

例如,perlish解决方案如下所示:

my $num = '1234567890';
while ($num =~ s/^(.*?,)?(\d{1,3})((?:\d{3})+)$/$1$2,$3/) {}

答案 9 :(得分:0)

我将把downvotes当作不是要求的语言,但是这种非正则表达式技术应该适用(我是通过搜索“ C#regex将逗号添加到数字中”到达这里的)

TabView

导致:

var raw = "104241824 15202656 KB 13498560 KB 1612672KB already 1,000,000 or 99.999 or 9999.99"; int i = 0; bool isnum = false; var formatted = raw.Reverse().Aggregate(new StringBuilder(), (sb, c) => { //$"{i}: [{c}] {isnum}".Dump(); if (char.IsDigit(c) && c != ' ' && c!= '.' && c != ',') { if (isnum) { if (i == 3) { //$"ins ,".Dump(); sb.Insert(0, ','); i = 0; } } else isnum = true; i++; } else { isnum = false; i = 0; } sb.Insert(0, c); return sb; });

答案 10 :(得分:-1)

试试这段代码。它简单而且性能最佳。

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

答案 11 :(得分:-1)

Perl RegExp 1衬板:

1 while $VAR{total} =~ s/(.*\d)(\d\d\d)/$1,$2/g;