Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Add Thousands Separator


  • Please log in to reply
21 replies to this topic
infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
Here is a simple one-liner regex/function that add thousands separators to the correct spots in any decimal number with no loops, no recursion, and no callouts:

You can specify your own group separator either when you call it or you can modify the value in the function definition to match your locale.

ThousandsSep(x, s=",") {
	return RegExReplace(x, "\G\d+?(?=(\d{3})+(?:\D|$))", "$0" s)
}

And here is the test code I used for validating it, and the old version:
MsgBox % ""
	. "`n" ThousandsSep(1) 
	. "`n" ThousandsSep(12) 
	. "`n" ThousandsSep(123) 
	. "`n" ThousandsSep(1234) 
	. "`n" ThousandsSep(12345) 
	. "`n" ThousandsSep(123456) 
	. "`n" ThousandsSep(1234567) 
	. "`n" ThousandsSep(12345678) 
	. "`n" ThousandsSep(123456789) 
	. "`n" ThousandsSep(1234567890) 
	. "`n" ThousandsSep(1.1) 
	. "`n" ThousandsSep(12.12) 
	. "`n" ThousandsSep(123.123) 
	. "`n" ThousandsSep(1234.1234) 
	. "`n" ThousandsSep(12345.12345) 
	. "`n" ThousandsSep(123456.123456) 
	. "`n" ThousandsSep(1234567.1234567) 
	. "`n" ThousandsSep(12345678.12345678) 
	. "`n" ThousandsSep(123456789.123456789) 
	. "`n" ThousandsSep(1234567890.1234567890)
; old version:      RegExReplace(x, "(?(?<=\" d ")(*COMMIT)(*FAIL))\d(?=(\d{3})+(\D|$))", "$0" g)
; old old version: RegExReplace(x, "(?(?<=\.)(*COMMIT)(*FAIL))(?<=\d)(\d{3})(?=(?:\d{3})*+(?:$|\.))", ",$1")


sinkfaze
  • Moderators
  • 6367 posts
  • Last active: Nov 30 2018 08:50 PM
  • Joined: 18 Mar 2008
Very nice!

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Cool! Maybe the regex can be simplified a bit, keeping the conditional idea:
RegExReplace(x, "(?(?<=\.)(*COMMIT)(*FAIL))\d(?=(\d{3})+(\D|$))", "$0,")


infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
Laszlo: That's a good idea, I'll change it.

Thanks guys. :)

infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
In response to the need shown in this thread, I decided to add an optional param for specifying your own seperator.

Updated. :)

Delusion
  • Members
  • 272 posts
  • Last active: Jul 13 2014 09:04 PM
  • Joined: 16 Jul 2008
great! thank you very much for this
QuickSubs | Popcorn Movie Catalog
All my scripts are just in AutoHotkey v1.0.48.05

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005

specifying your own seperator...

Maybe specifying the decimal separator (period or comma) would be helpful, too. It could default to the one specified by the user's locale, and then the default group separator might be the other character.

TheGood
  • Members
  • 589 posts
  • Last active: Mar 22 2014 03:22 PM
  • Joined: 30 Jul 2007
Very elegant! Can you explain how the COMMIT and FAIL verbs work? I had a look at the PCRE docs but still can't wrap my head around it.

Tuncay
  • Members
  • 1945 posts
  • Last active: Feb 08 2015 03:49 PM
  • Joined: 07 Nov 2006
Thx for the function. I have also made a solution, but that function is gone away. How? Harddisk crash!!
Btw, very very elegant. I name you to king Thousand! :D

No signature.


infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008

Maybe specifying the decimal separator (period or comma) would be helpful, too.

Ah, good point! So I added another param to the function above.

However, I don't know how one could get the separator characters based on the user's current locale without a bunch of complexity. I mentioned that the params could be modified by the user.

TheGood: COMMIT and FAIL has to do with the flow of running a regex on text. To compare it to a loop, a plain FAIL would be like Continue, but COMMIT FAIL would be like a Break. The end result in this regex is to completely quit the regex and return once it passes a decimal point, since you don't want it adding separators after the decimal point. (e.g. 12.123,456,789 would be bad)

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
At least in Win7 you can get the decimal and thousand separator of the user's locale, from the registry:
RegRead d, HKEY_CURRENT_USER ,Control Panel\International, sDecimal

RegRead t, HKEY_CURRENT_USER ,Control Panel\International, sThousand



infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
Well I asked in <!-- m -->irc://freenode.net/#regex<!-- m --> and Billiard came up with a similar solution for this that doesn't require specifying the decimal character. Find it in the first post.

Instead of using COMMIT FAIL, it uses the \G anchor (which I didn't know existed :S). The \G anchor forces it to match either at the very beginning of the string or at the end of the previous match. Since a decimal separator won't match, it forces a fail at that point, regardless of what kind of decimal separator it is.

Laszlo: I figured one could easily get the values from the registry, but I'm saying it's out of the scope of this function. Thanks for the info though; now if someone does want to make a locale-specific ThousandsSep function, they have the resources right here to do it. :)

Zod
  • Members
  • 214 posts
  • Last active: Jan 26 2012 08:02 PM
  • Joined: 06 Jul 2011
Wonder:

would it be possible to strip word characters easily?
Posted Image Stolen from SKAN

infogulch
  • Moderators
  • 717 posts
  • Last active: Jul 31 2014 08:27 PM
  • Joined: 27 Mar 2008
Zod: by "strip word characters" I assume you're talking about non-numeric characters in the string with the number.

In that case I would instead suggest that you extract out all the numbers, add thousands separators to them with this function, then replace them in the original string or some similar combination.

Zod
  • Members
  • 214 posts
  • Last active: Jan 26 2012 08:02 PM
  • Joined: 06 Jul 2011
yea was just hoping for one step instead of 2
Posted Image Stolen from SKAN