Comma Delimit a Number

I’m trying to add the commas to numbers like 26478940 i.e. 26,578,940

I got as far as a script to add commas after every character but am having
trouble getting it to do it correctly, every 3rd character.

My Indigo home automation app is handling the value of the number, just need
to get the commas added.

tell application "IndigoServer"
	set theStock to value of variable "Stock1"
	set stockVol to do shell script "curl -s 'http://download.finance.yahoo.com/d/quotes.csv?s=" & theStock & "&f=v'"
	
	set theNumber to stockVol
	set AppleScript's text item delimiters to ","
	set theItems to every character of theNumber as string
	set AppleScript's text item delimiters to ""
	
	
	set value of variable "Stock1Volume" to theItems
	
end tell


Appreciate any input on how to get it to do correct commas.

Thanks,

Carl

Hi ckeyes888,

Are there ever any decimals in the number?

gl,
kel

Nope. Always just numbers of varying length.

Thanks,

Carl

Hello.

Maybe you can use this.

thouDelimit(12345678)

on thouDelimit(aNumber)
	script o
		property cin : {}
	end script
	local cout
	set cout to {}
	set o's cin to reverse of every character of (aNumber as text)
	
	repeat with i from 1 to (length of o's cin)
		set end of cout to item i of o's cin
		if i mod 3 = 0 then set end of cout to ","
	end repeat
	return (reverse of cout as text)
end thouDelimit


For users working with the French rules : decimal comma and thousands separator No Break Space, edit
if i mod 3 = 0 then set end of cout to “,”
as
if i mod 3 = 0 then set end of cout to character ID 160

Yvan KOENIG (VALLAURIS, France) vendredi 15 novembre 2013 19:01:23

Hello.

I guess the rules Ckeyes888 are using are “ticker - rules”. :wink:

By the way, here is a slightly improved version.

thouDelimit("2345678992222222")

on thouDelimit(aNumber)
	local cout, cin
	set cout to ""
	set cin to reverse of every character of (aNumber as text) as text
	set theLast to ((length of cin) div 3) + 1
	repeat with i from 1 to (theLast)
		try
			if i < theLast then
				set cout to cout & text (1 + ((i - 1) * 3)) thru (i * 3) of cin & ","
			else
				set cout to cout & text (1 + ((i - 1) * 3)) thru (i * 3) of cin
			end if
		on error
			set cout to cout & text (1 + ((i - 1) * 3)) thru -1 of cin
		end try
	end repeat
	return (reverse of every character of cout as text)
end thouDelimit

I was thinking that stocks might have the last 2 numbers as cents.

Hello.
I think they at least removed the quarter cents from the stocks some years ago now.
Cents’ doesn’t give much meaning if you need thousands separators, maybe for points or yield or whatever.
I have no idea. :slight_smile:

Wow, thousand dollar a stock!

Hello.

I actually think the version below to be the best regarding speed, since I have removed the character operations.

thouDelimit("578940585")

on thouDelimit(aNumber)
	
	tell (length of aNumber)
		set iter to it div 3
		set trest to it mod 3
	end tell
	if trest > 0 and iter > 0 then
		-- we are having something longer than 3
		set {iter, aNumber, startpos} to ¬
			{iter - 1, ¬
				text 1 thru trest of aNumber & "," & ¬
				text (trest + 1) thru -1 of aNumber, ¬
				trest + 1}
		
	else if iter = 1 then
		set iter to 0 -- 3 digits
	else -- longer than 3 but no rest
		set {startpos, iter} to {0, iter - 1}
	end if
	
	repeat with i from 1 to iter
		set aNumber to ¬
			text 1 thru (startpos + i * 3) of aNumber & ¬
			"," & text (startpos + i * 3 + 1) thru -1 of aNumber
		set startpos to startpos + 1
	end repeat
	return aNumber
end thouDelimit

 property kSep : ","

set n to "1234567890123456789"
do shell script ("sed -En ':loop\\'$'\\n'';s/([0-9])([0-9]{3})[[:>:]]/\\1" & kSep & "\\2/;t loop\\'$'\\n''p' <<<" & n)

:slight_smile:

Hello.

It is shorter, but I dare say mine is a bit faster (the last one). :slight_smile: 58 (yours) /0.33 (mine) in Milliseconds; I ran both several times, but it is no serious timing.

When you start using loops in Sed I’t’s getting serious.:slight_smile:

Hello.

Actually, I find the way Nigel uses the $'s to be more serious. (I haven’t found a word of it in the release notes, but I am dead sure there is more going on in the do shell script command nowadays, you can’t for instance send an osascript command, within a do shell script command to the background anymore. Maybe I never noticed that I couldn’t, but I believe I did it. My point is, that a do shell script doesn’t get to be executed blindly anymore, like it used to, when you look away from the setup of the pseudo terminal device, which controlled whether a do shell script command will “hang” waiting. Now it “hangs” if you have the osascript command inside your do shell script.

Hi McUsr,

I haven’t notice that and I’ve run a lot of shell scripts since Mavericks. Interesting observation.

Edited: in fact, I was just thinking about a script with that.

Edited: the $ sing

Later,
kel

Thanks a bunch everyone. They all work beautifully.

Carl

thouDelimit("1234567890123456789", ",")

on thouDelimit(n, delim)
	set nLen to (count n)
	if (nLen < 4) then
		set n2 to n
	else
		set n2 to ""
		repeat with i from ((count n) - 2) to 2 by -3
			set n2 to delim & text i thru (i + 2) of n & n2
		end repeat
		set n2 to text 1 thru (i - 1) of n & n2
	end if
	return n2
end thouDelimit

:slight_smile:

I can’t think so far of an example where $ wouldn’t work. Can you give an example?

Edited: a simple example, please. :slight_smile:

Hello.

Nigels vanilla handler has a best time of 0.255 millsecs, mine has 0.274 millisecs. (Or around that, I just hit run again and again on both.) :slight_smile: I don’t know how the average results would turn out, but I have a feeling that Nigel’s handler would beat mine with more than 0.019 milliseconds on average!

@ Kel: I meant the usage of the ‘$’ construct as a linefeed in a do shell script, not in a regular expression.

A linefeed? Some of your unix stuff is beyond me.