Jump to content

commify


avery
 Share

Recommended Posts

I have some numbers I store and they show up like 213453 and 46734537.

I would like to try to add comma's to them but I suck terribly with regex to do this using search and replace.

Can any regex Guru's please help me write a function to add comma's to a variable?

perhaps I feed the function a var that is a number and it returns the same number with comma's added every third character.

Please and thank you anyone who is willing to help me. I looked for a built-in and I found stringsub but am not sure if that can work for this.

Respectfully,

Avery

www.abox.orgAvery HowellVisit My AutoIt Websitehttp://www.abox.org
Link to comment
Share on other sites

Something like this? Not perfect, but should give a start:

Local $sTest = '46734537'
$sTest = StringRegExpReplace($sTest, '(\d{0,2})(\d{3}+)', '$1,$2$3$4')
ConsoleWrite($sTest & @crlf )
No, doesn't do it. :) Edited by memoryoverflow

(The signature is placed on the back of this page to not disturb the flow of the thread.)

Link to comment
Share on other sites

Here is a function using a regular expression in a loop that does a good job of adding commas to numbers in the appropriate places

;Example 1
$number = 4673453.987
$DisplayNumber = _Commify($number)
MsgBox(0,"Commify",$DisplayNumber)

Example 2
$number = "This is a number in a string 4673453 surrounded by text"
$DisplayNumber = _Commify($number)
MsgBox(0,"Commify",$DisplayNumber)


Func _Commify($number)
    Do
    $number = StringRegExpReplace($number, "(?<=[0-9])(?=(?:[0-9]{3})+(?![0-9]))", ",")
    Until @extended = 0
    Return $number
EndFunc

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Link to comment
Share on other sites

Another way

#include<string.au3>
$iStr = 1234567890
MsgBox(0, "Result", _AddCommas($iStr))

Func _AddCommas($i_Val)
    Local $iVal = _StringReverse($i_Val), $sRtn = ""
    For $i = 1 To StringLen($iVal) Step 3
        Local $iHold = StringMid($iVal, $i, 3)
        If StringLen($iHold) = 3 Then $iHold &= ","
        $sRtn &= $iHold
    Next
    If $sRtn Then Return _StringReverse($sRtn)
    Return $i_Val
EndFunc   ;;<===>_AddCommas

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

And here's the 1-liner, not exactly elegant, but does the job:

Local $sTest = '98765432123456789'
ConsoleWrite($sTest & ' = ' & StringLeft($sTest, 1 + Mod(StringLen($sTest) - 1, 3)) & StringRegExpReplace(StringMid($sTest, 2 + Mod(StringLen($sTest) - 1, 3)), '(\G\d{3})',',$1') & @crlf )

(The signature is placed on the back of this page to not disturb the flow of the thread.)

Link to comment
Share on other sites

@Bowmore,

Loops? we don't need no stinkin' loops:

$number = StringRegexpReplace($number,"(?<!\.)(\d)(?=(\d{3})+(?!\d))","\1,")

But, add an extra decimal place to yours or mine and they fail by commifying after the decimal.

@GEOSoft

Your fails with even 1 decimal place (but I know you'll fix that :) )

@memoryoverflow

Your last one seems to work in all cases on a string that's only a number, with no other text.

So does this RegExp

$number = StringRegexpReplace($number,"((?<!.)\d{1,3}|\G\d{3})(?=(?:\d{3})+(?!\d))","\1,")

Again, this also fails on something like in Bowmore's Ex. # 2

$number = "This is a number in a string 4673453.7685 surrounded by text"

I know there's more that could be added to this last RegExp to handle the text situation too, but right now my brain's too tired... :)
Link to comment
Share on other sites

@GEOSoft

Your fails with even 1 decimal place (but I know you'll fix that :) )

I might but it won't be tonight for sure. Besides, who mentioned anything about floats?

That could be fixed easily by stripping the decimal portion first then adding it back at the end.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

To allow for negative numbers, this appears to work.

$sNumber = StringRegexpReplace($number,"((?<!.)(\D{0,2})\d{1,3}|\G\d{3})(?=(?:\d{3})+(?!\d))","\1,")

If this regular expression can not be improved, it may make a suitable alternative to the ex _StringAddThousandsSep function.

The example here also works. This being my contribution to having _StringAddThousandsSep function erased from AutoIt.

Here is a little testing example.

;=================================
; Malkey added (\D{0,2})to ResNullius RE pattern.
Local $number = '-$765432123456789.98765'

$sNumber = StringRegexpReplace($number,"((?<!.)(\D{0,2})\d{1,3}|\G\d{3})(?=(?:\d{3})+(?!\d))","\1,")

ConsoleWrite($sNumber & @CRLF)

;====================================
;@memoryoverflow
Local $sTest = '-765432123456789'
ConsoleWrite($sTest & ' = ' & StringLeft($sTest, 1 + Mod(StringLen($sTest) - 1, 3)) & StringRegExpReplace(StringMid($sTest, 2 + Mod(StringLen($sTest) - 1, 3)), '(\G\d{3})',',$1') & @crlf)
;Result is -,765,432,123,456,789
;==========================================

;=========================================
;From current String.au3 include file. Not in latest beta version because,
;"There are too many opinions on what this function should do and too many revisions of this function have been made.
; http://www.autoitscript.com/forum/index.php?showtopic=104014&view=findpost&p=736303
; Translated to:-
; Noone would agree with Valik's opinion, so he wrote another version that didn't work.

Local $sTest = '-765432123456789'

ConsoleWrite("String.au3 File: " & _StringAddThousandsSep($sTest) & @CRLF)
;Result is String.au3 File: -,765,432,123,456,789
; #FUNCTION# ====================================================================================
; Name...........: _StringAddThousandsSep
; Description ...: Returns the original numbered string with the Thousands delimiter inserted.
; Syntax.........: _StringAddThousandsSep($sString[, $sThousands = -1[, $sDecimal = -1]])
; Parameters ....: $sString - The string to be converted.
;   $sThousands - Optional: The Thousands delimiter
;   $sDecimal - Optional: The decimal delimiter
; Return values .: Success - The string with Thousands delimiter added.
; Author ........: SmOke_N (orignal _StringAddComma
; Modified.......: Valik (complete re-write, new function name)
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; =================================================================================================
Func _StringAddThousandsSep($sString, $sThousands = -1, $sDecimal = -1)
    Local $sResult = "" ; Force string
    Local $rKey = "HKCU\Control Panel\International"
    If $sDecimal = -1 Then $sDecimal = RegRead($rKey, "sDecimal")
    If $sThousands = -1 Then $sThousands = RegRead($rKey, "sThousand")
;~  Local $aNumber = StringRegExp($sString, "(\d+)\D?(\d*)", 1)
    Local $aNumber = StringRegExp($sString, "(\D?\d+)\D?(\d*)", 1) ; This one works for negatives.
    If UBound($aNumber) = 2 Then
        Local $sLeft = $aNumber[0]
        While StringLen($sLeft)
            $sResult = $sThousands & StringRight($sLeft, 3) & $sResult
            $sLeft = StringTrimRight($sLeft, 3)
        WEnd
;~      $sResult = StringTrimLeft($sResult, 1) ; Strip leading thousands separator
        $sResult = StringTrimLeft($sResult, StringLen($sThousands)) ; Strip leading thousands separator
        If $aNumber[1] <> "" Then $sResult &= $sDecimal & $aNumber[1]
    EndIf
    Return $sResult
EndFunc ;==>_StringAddThousandsSep
;=================================================================
Link to comment
Share on other sites

To allow for negative numbers, this appears to work.

$sNumber = StringRegexpReplace($number,"((?<!.)(\D{0,2})\d{1,3}|\G\d{3})(?=(?:\d{3})+(?!\d))","\1,")

If this regular expression can not be improved, it may make a suitable alternative to the ex _StringAddThousandsSep function.

The example here also works. This being my contribution to having _StringAddThousandsSep function erased from AutoIt.

Here is a little testing example.

;=================================
; Malkey added (\D{0,2})to ResNullius RE pattern.
Local $number = '-$765432123456789.98765'

$sNumber = StringRegexpReplace($number,"((?<!.)(\D{0,2})\d{1,3}|\G\d{3})(?=(?:\d{3})+(?!\d))","\1,")

ConsoleWrite($sNumber & @CRLF)

;====================================
;@memoryoverflow
Local $sTest = '-765432123456789'
ConsoleWrite($sTest & ' = ' & StringLeft($sTest, 1 + Mod(StringLen($sTest) - 1, 3)) & StringRegExpReplace(StringMid($sTest, 2 + Mod(StringLen($sTest) - 1, 3)), '(\G\d{3})',',$1') & @crlf)
;Result is -,765,432,123,456,789
;==========================================

;=========================================
;From current String.au3 include file. Not in latest beta version because,
;"There are too many opinions on what this function should do and too many revisions of this function have been made.
; http://www.autoitscript.com/forum/index.php?showtopic=104014&view=findpost&p=736303
; Translated to:-
; Noone would agree with Valik's opinion, so he wrote another version that didn't work.

Local $sTest = '-765432123456789'

ConsoleWrite("String.au3 File: " & _StringAddThousandsSep($sTest) & @CRLF)
;Result is String.au3 File: -,765,432,123,456,789
; #FUNCTION# ====================================================================================
; Name...........: _StringAddThousandsSep
; Description ...: Returns the original numbered string with the Thousands delimiter inserted.
; Syntax.........: _StringAddThousandsSep($sString[, $sThousands = -1[, $sDecimal = -1]])
; Parameters ....: $sString - The string to be converted.
;   $sThousands - Optional: The Thousands delimiter
;   $sDecimal - Optional: The decimal delimiter
; Return values .: Success - The string with Thousands delimiter added.
; Author ........: SmOke_N (orignal _StringAddComma
; Modified.......: Valik (complete re-write, new function name)
; Remarks .......:
; Related .......:
; Link ..........;
; Example .......; Yes
; =================================================================================================
Func _StringAddThousandsSep($sString, $sThousands = -1, $sDecimal = -1)
    Local $sResult = "" ; Force string
    Local $rKey = "HKCU\Control Panel\International"
    If $sDecimal = -1 Then $sDecimal = RegRead($rKey, "sDecimal")
    If $sThousands = -1 Then $sThousands = RegRead($rKey, "sThousand")
;~  Local $aNumber = StringRegExp($sString, "(\d+)\D?(\d*)", 1)
    Local $aNumber = StringRegExp($sString, "(\D?\d+)\D?(\d*)", 1) ; This one works for negatives.
    If UBound($aNumber) = 2 Then
        Local $sLeft = $aNumber[0]
        While StringLen($sLeft)
            $sResult = $sThousands & StringRight($sLeft, 3) & $sResult
            $sLeft = StringTrimRight($sLeft, 3)
        WEnd
;~      $sResult = StringTrimLeft($sResult, 1) ; Strip leading thousands separator
        $sResult = StringTrimLeft($sResult, StringLen($sThousands)) ; Strip leading thousands separator
        If $aNumber[1] <> "" Then $sResult &= $sDecimal & $aNumber[1]
    EndIf
    Return $sResult
EndFunc ;==>_StringAddThousandsSep
;=================================================================

The last version of that function (now removed from AutoIt) is here.

http://dundats.mvps.org/autoit/udf_code.aspx?udf=stringx

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

This looked fun for those who participated :) However I am not normally given so many solutions for a problem lol. I am not sure which one I should use lol. PS: You all freaking rock. Now -- Who's is better!?! LOL :)

I would like to start by saying a really big thank you to the (always) awesome au3 community! It's largely do to the well written, mainly complete, au3 documentation and knowledgeable au3 community that makes me absolutely love this language and prefer it over all others!

www.abox.orgAvery HowellVisit My AutoIt Websitehttp://www.abox.org
Link to comment
Share on other sites

Use any of them depending on what you are doing. If you are working with strictly positive whole numbers then they all work. The one I posted won't work with floats and the link I provided does it all even if there was existing separators and is really just a slightly later version than the one Malkey posted. If you are using the last release version then the function is already in there but it has been removed in the later Beta versions.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

Use any of them depending on what you are doing. If you are working with strictly positive whole numbers then they all work. The one I posted won't work with floats and the link I provided does it all even if there was existing separators and is really just a slightly later version than the one Malkey posted. If you are using the last release version then the function is already in there but it has been removed in the later Beta versions.

Understand & Thank you again.

I am going to hit the donate button today because I think it's the right thing to do. The forums get ten more bucks from me this month :) Thanks again for the awesome help everyone.

www.abox.orgAvery HowellVisit My AutoIt Websitehttp://www.abox.org
Link to comment
Share on other sites

Here is something me and another member posted a few month ago on the Example forum but I think that because we've overtaken one member's topic we've deleted our posts but you'll find it to be accurate, I hope. Benchmarks are included.

#include <String.au3>

Dim $sStr = '-112123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432' & _
        '123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432' & _
        '123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432' & _
        '123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432' & _
        '123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432123456789098765432' & _
        '12345678909876543212345678909876543212345678909876543212345678909876543212345678909876543212.3456789098765432'

Dim $i, $TimerInit, $TimerDiff
Dim $sResult

$TimerInit = TimerInit()
For $i = 0 To 50
    $sResult = _ITS($sStr)
Next
MsgBox(0x40, '_ITS', $sResult & @CRLF & @CRLF & 'Took(ms): ' & TimerDiff($TimerInit))


$TimerInit = TimerInit()
For $i = 0 To 50
    $sResult = _StringAddThousandsSep($sStr)
Next
MsgBox(0x40, 'STS', $sResult & @CRLF & @CRLF & 'Took(ms): ' & TimerDiff($TimerInit))


Func _ITS($sText, $Sep = ',', $Dec = '.')
    If Not StringIsInt($sText) And Not StringIsFloat($sText) Then Return SetError(1, 0, $sText)

    Local $aSplit = StringSplit($sText, $Dec)
    Local $iTrim
    Local $sTmp = ''


    If StringLeft($aSplit[1], 1) = '-' Then
        $iTrim = 1
    Else
        $iTrim = 0
    EndIf

    Switch $aSplit[0]
        Case 1
            Switch Mod(StringLen($aSplit[1]) - $iTrim, 3)
                Case 1
                    Return StringRegExpReplace($aSplit[1], '(?<=\d)(\d{3})', $Sep & '\1')
                Case 0
                    Return StringRegExpReplace($aSplit[1], '(\d{3})(?!$)', '\1' & $Sep)
                Case 2
                    $sTmp = StringRight($aSplit[1], StringLen($aSplit[1]) - 2 - $iTrim)
                    $sTmp = StringRegExpReplace($sTmp, '(\d{3})', $Sep & '\1')
                    Return StringLeft($aSplit[1], 2 + $iTrim) & $sTmp
            EndSwitch

        Case 2
            Switch Mod(StringLen($aSplit[1]) - $iTrim, 3)
                Case 1
                    Return StringRegExpReplace($aSplit[1], '(?<=\d)(\d{3})', $Sep & '\1') & $Dec & $aSplit[2]
                Case 0
                    Return StringRegExpReplace($aSplit[1], '(\d{3})(?!$)', '\1' & $Sep) & $Dec & $aSplit[2]
                Case 2
                    $sTmp = StringRight($aSplit[1], StringLen($aSplit[1]) - 2 - $iTrim)
                    $sTmp = StringRegExpReplace($sTmp, '(\d{3})', $Sep & '\1')
                    Return StringLeft($aSplit[1], 2 + $iTrim) & $sTmp & $Dec & $aSplit[2]
            EndSwitch
    EndSwitch
EndFunc   ;==>_ITS
Edited by Authenticity
Link to comment
Share on other sites

Finally got it to work with a single PCRE RegEx

The following pattern would give the desired result with some RegEx engines .Net is one

"(?<=\d)(?=(?:\d{3})+(?!\d))(?<!\.\d+)"

but unfortunately not with the PCRE as the PCRE library does not support infinite repetition inside lookbehind so you have to be a bit more expicit.

$number = 1.123456789012
$DisplayNumber = StringRegExpReplace($number, "(?!\.)(\d)(?=(?:\d{3})+(?!\d))(?<!\.\d{1}|\.\d{2}|\.\d{3}|\.\d{4}|\.\d{5}|\.\d{6}|\.\d{7}|\.\d{8}|\.\d{9})", "\1,")
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $DisplayNumber = ' & $DisplayNumber & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

$number = 123456789.123456789012
$DisplayNumber = StringRegExpReplace($number, "(?!\.)(\d)(?=(?:\d{3})+(?!\d))(?<!\.\d{1}|\.\d{2}|\.\d{3}|\.\d{4}|\.\d{5}|\.\d{6}|\.\d{7}|\.\d{8}|\.\d{9})", "\1,")
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $DisplayNumber = ' & $DisplayNumber & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

$number = "This is some text 123456789.123456789012 This is some more text"
$DisplayNumber = StringRegExpReplace($number, "(?!\.)(\d)(?=(?:\d{3})+(?!\d))(?<!\.\d{1}|\.\d{2}|\.\d{3}|\.\d{4}|\.\d{5}|\.\d{6}|\.\d{7}|\.\d{8}|\.\d{9})", "\1,")
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $DisplayNumber = ' & $DisplayNumber & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...