|
|
|||||||||
|
|||||||||
| |||||||||
|
|
|
| |||||||||
![]() |
|
|
«
Previous Thread
|
Next Thread
»
|
Thread Tools | Search this Thread | Rate Thread | Display Modes |
|
|
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
|
|||
|
|||
|
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 |
|
#2
|
||||
|
||||
|
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. Last edited by netytan : February 12th, 2004 at 04:26 PM. |
|
#3
|
||||
|
||||
|
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. |
|
#4
|
|||
|
|||
|
netytan: FYI, it's list comprehensions, not compressions
![]() |
|
#5
|
||||
|
||||
|
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. |
|
#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. |
|
#7
|
|||
|
|||
|
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. |
|
#8
|
||||
|
||||
|
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 |
|
#9
|
||||
|
||||
|
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. |
|
#10
|
||||
|
||||
|
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 |
|
#11
|
|||
|
|||
|
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 |
|
#12
|
||||
|
||||
|
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. |
|
#13
|
|||
|
|||
|
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 |