Python Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me
Go Back   Dev Shed ForumsProgramming LanguagesPython Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
AT&T devCentral & BlackBerry(r) Webcast Series: BlackBerry and GPS -Build Location Awareness into your BlackBerry Applications, July 10th-1:00PM EST. Register Today!
  #1  
Old February 12th, 2004, 01:18 AM
theperfectsoup theperfectsoup is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jul 2003
Posts: 35 theperfectsoup User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 5
Injecting commas to long numbers?

Hi all,

Anyone know of a built-in or easy way to turn a number like 3961037749 into the string "3,961,037,749"?

Thanks,
tps

Reply With Quote
  #2  
Old February 12th, 2004, 09:59 AM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,529 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 17 h 19 m 5 sec
Reputation Power: 63
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
There might be a betetr way to do this but i'm not aware of it if there is.. sooo, i've writen a few different versions of the inject functions.

Code:
def inject(number):
	string = str(number)
	cursor = 0
	output = []

	for number in string[::-1]:
		if not cursor % 3:
			number = number + ','
		cursor = cursor + 1
		output.append(number)
		
	output.reverse()

	return ''.join(output)[:-1]

Code:
def inject(number):
	string = str(number)
	output = []
	
	for index, value in enumerate(string):
		if not index % 3:
			value = string[index - len(string)] + ','
		output.append(value)
	return ''.join(output)[:-1]


I'm also gonna see if this can be done with list comprehensions. We'll see

Mark.
__________________
programming language development: www.netytan.com Hula


Last edited by netytan : February 12th, 2004 at 04:26 PM.

Reply With Quote
  #3  
Old February 12th, 2004, 11:14 AM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,529 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 17 h 19 m 5 sec
Reputation Power: 63
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
Ok admitadly this is actualy two functions but unfortunatly needed...

Code:
def insert(i, v):
	if not i % 3: v = v + ','; return v

def inject(n):
	return ''.join([insert(i, v) for i, v in enumerate(str(n))])[:-1]


Obviously using list comprehensions . Which has its limitations. Still works though , although personally i'd use one of the functions above.

Mark.

Last edited by netytan : February 12th, 2004 at 04:25 PM.

Reply With Quote
  #4  
Old February 12th, 2004, 03:42 PM
Strike Strike is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2001
Location: Houston, TX
Posts: 383 Strike User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 1 h 41 m 27 sec
Reputation Power: 7
Send a message via ICQ to Strike Send a message via AIM to Strike Send a message via Yahoo to Strike
netytan: FYI, it's list comprehensions, not compressions

Reply With Quote
  #5  
Old February 12th, 2004, 04:24 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,529 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 17 h 19 m 5 sec
Reputation Power: 63
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
Hahhaha i so didn't spot that need to think more . Ah it could be worse though, this guy i used to work for couldnt stop himself typing sausage instead of some word... every time he tried to type this word he'd type sausage lol

Mark.

Reply With Quote
  #6  
Old February 12th, 2004, 04:49 PM
percivall percivall is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Jul 2003
Posts: 133 percivall User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 6
Here's a nice and uncomplicated implementation that might be fun to parse:
Code:
def commatize(num):
    if type(num) is not str:
        num = str(num)
    return ",".join([part for part in\
                     [num[x*-3:len(num)+3+(x*-3)]
                      for x in range(1, len(num) / 3 + 2)][::-1]
                     if len(part) != 0])

This is the true one-liner, considering that you could easily remove the "if type..." part of the code. On the other hand: I too would rather use the more verbose code.

Last edited by percivall : February 12th, 2004 at 05:07 PM.

Reply With Quote
  #7  
Old February 12th, 2004, 07:56 PM
Strike Strike is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Dec 2001
Location: Houston, TX
Posts: 383 Strike User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: 1 h 41 m 27 sec
Reputation Power: 7
Send a message via ICQ to Strike Send a message via AIM to Strike Send a message via Yahoo to Strike
Another version, just for fun:
Code:
def commatize(num):
    L = list(str(num))
    for add, pos in enumerate(range(3, len(L), 3)):
        L.insert(-(add+pos), ',')
    return ''.join(L)

it's sort of the one-function version of netytan's shortest.

Reply With Quote
  #8  
Old February 13th, 2004, 02:58 AM
Grim Archon's Avatar
Grim Archon Grim Archon is offline
Mini me.
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2003
Location: Cambridge, UK
Posts: 783 Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)  Folding Points: 1488 Folding Title: Novice Folder
Time spent in forums: 3 Days 2 h 15 m 57 sec
Reputation Power: 7
Send a message via MSN to Grim Archon
Just adding to the mix
The Good :
Code:
def comma5(num):
    d = `num`[::-1]
    r = ''
    for c in range(0,len(d),3):
        r = r+d[0:3]+','
        d = d[3:]
    if r[-1] == ',':
        r = r[:-1]
    return r[::-1]

The Bad and the Ugly(ist) code I've ever written
Code:
def comma3(num):
    d= ''.join(map(lambda x, y : x+[',',''][(y+1)%3 and 1],list(`num`)[::-1],range(len(list(`a`)))))
    return d[:len(d)-(d[-1]==',')][::-1]

comma5 is fast, comma3 is SO slow.
Grim

Reply With Quote
  #9  
Old February 13th, 2004, 05:23 PM
netytan's Avatar
netytan netytan is offline
Hello World :)
Dev Shed Frequenter (2500 - 2999 posts)
 
Join Date: Mar 2003
Location: Hull, UK
Posts: 2,529 netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level)netytan User rank is Second Lieutenant (5000 - 10000 Reputation Level) 
Time spent in forums: 1 Week 2 Days 17 h 19 m 5 sec
Reputation Power: 63
Send a message via ICQ to netytan Send a message via AIM to netytan Send a message via MSN to netytan Send a message via Yahoo to netytan
Ok i finally got it figured it out, with a little inspiration from you're examples.

No i don't clame its the most efficent function because i can see places that could be improved on i.e. the two str() calls would normally be singular, but since the aim of this example was to write a totaly self contained one liner it had to be so.

Code:
def inject(number): return ','.join([str(number)[::-1][index:index + 3][::-1] for index in range(0, len(str(number)), 3)][::-1])


If you can see ways to shorten this further i'd love to hear them.

Grim: way, you were right, you can do this with map and lambda *shakes you're hand as promised*

Mark.

Reply With Quote
  #10  
Old February 13th, 2004, 06:18 PM
Grim Archon's Avatar
Grim Archon Grim Archon is offline
Mini me.
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2003
Location: Cambridge, UK
Posts: 783 Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)  Folding Points: 1488 Folding Title: Novice Folder
Time spent in forums: 3 Days 2 h 15 m 57 sec
Reputation Power: 7
Send a message via MSN to Grim Archon
Netyan,full marks for
But, my comma5 is still twice as fast as the worst posted (my comma3 func ) and 40% faster than the next best
Grim

Reply With Quote
  #11  
Old February 19th, 2004, 11:32 AM
DevCoach DevCoach is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2004
Location: London, England
Posts: 1,193 DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level) 
Time spent in forums: 1 Week 5 Days 12 h 59 m 24 sec
Reputation Power: 252
A recursive alternative

All the solutions given so far work by treating the number as a string or list of characters, and chopping it up/inserting characters.

Here is an alternative that works by recursively dividing the number by 1000:

Code:
>>> def comma(x): return x < 1000 and str(x) or ('%s,%03d' % (comma(x//1000), (x%1000)))
...
>>> comma(30498523409562345923459085340L)
'30,498,523,409,562,345,923,459,085,340'


I have not benchmarked it against the other versions - that is left as an exercise for the reader.

The function also only works with positive integers. It can be made to work with negative numbers, but would not be such a neat one-liner.

Dave - The Developers' Coach

Last edited by DevCoach : February 19th, 2004 at 11:37 AM. Reason: fixed typo in the code

Reply With Quote
  #12  
Old February 19th, 2004, 04:27 PM
Grim Archon's Avatar
Grim Archon Grim Archon is offline
Mini me.
Dev Shed Novice (500 - 999 posts)
 
Join Date: Nov 2003
Location: Cambridge, UK
Posts: 783 Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)Grim Archon User rank is Corporal (100 - 500 Reputation Level)  Folding Points: 1488 Folding Title: Novice Folder
Time spent in forums: 3 Days 2 h 15 m 57 sec
Reputation Power: 7
Send a message via MSN to Grim Archon
Dave, that must be the last word in compactness and speed. A full 6% faster than my best effort
Another one to hurt my head
Grim
__________________
*** Experimental Python Markup CGI V2 ***

Last edited by Grim Archon : February 19th, 2004 at 04:35 PM. Reason: Added facts.

Reply With Quote
  #13  
Old February 19th, 2004, 05:29 PM
DevCoach DevCoach is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2004
Location: London, England
Posts: 1,193 DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level)DevCoach User rank is Captain (20000 - 30000 Reputation Level) 
Time spent in forums: 1 Week 5 Days 12 h 59 m 24 sec
Reputation Power: 252
improved recursive version

I have played around with this some more, and done some benchmarking. I found that two of the given solutions did not run, and two others gave the wrong answers for long integers (because the conversion to string added an 'L' on the end, which screwed up their indexing).

Of the ones that ran, my version was fastest for integers and grim's comma5 function was slightly faster for longs.

However all the functions so far failed for negative numbers - mine just returned the number unchanged, and all the others (that worked) when given a number like:

-450324598

returned:

-,450,324,598

here is a new version of my recursive function that correctly handles all cases, and has been re-written to be easier to read (this is Python after all, not Perl)

Code:
def comma(x):
   if x < 0: return '-' + comma(-x)
   if x < 1000: return str(x)
   return '%s,%03d' % (comma(x//1000), (x%1000))


Incidentally, the '//' operator is the 'floor division' operator introduced in 2.2 - for earlier versions of Python use '/'. At the moment they both give the same result, but in the future (I think in 2.4) the '/' operator on integers will convert the answer to a float when necessary.

Have a nice day

Dave - The Developers' Coach

Reply With Quote