Needed formatted numbers with thousands separator commas added on an end-user report. The usual way mentioned is to use 'module locale.format', but that didn't work cleanly on my Windows machine, and the cure seemed worse than the disease.
| Python |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | import re
__test__ = {}
re_digits_nondigits = re.compile(r'\d+|\D+')
__test__['re_digits_nondigits'] = r"""
>>> re_digits_nondigits.findall('$1234.1234')
['$', '1234', '.', '1234']
>>> re_digits_nondigits.findall('1234')
['1234']
>>> re_digits_nondigits.findall('')
[]
"""
def FormatWithCommas(format, value):
"""
>>> FormatWithCommas('%.4f', .1234)
'0.1234'
>>> FormatWithCommas('%i', 100)
'100'
>>> FormatWithCommas('%.4f', 234.5678)
'234.5678'
>>> FormatWithCommas('$%.4f', 234.5678)
'$234.5678'
>>> FormatWithCommas('%i', 1000)
'1,000'
>>> FormatWithCommas('%.4f', 1234.5678)
'1,234.5678'
>>> FormatWithCommas('$%.4f', 1234.5678)
'$1,234.5678'
>>> FormatWithCommas('%i', 1000000)
'1,000,000'
>>> FormatWithCommas('%.4f', 1234567.5678)
'1,234,567.5678'
>>> FormatWithCommas('$%.4f', 1234567.5678)
'$1,234,567.5678'
>>> FormatWithCommas('%i', -100)
'-100'
>>> FormatWithCommas('%.4f', -234.5678)
'-234.5678'
>>> FormatWithCommas('$%.4f', -234.5678)
'$-234.5678'
>>> FormatWithCommas('%i', -1000)
'-1,000'
>>> FormatWithCommas('%.4f', -1234.5678)
'-1,234.5678'
>>> FormatWithCommas('$%.4f', -1234.5678)
'$-1,234.5678'
>>> FormatWithCommas('%i', -1000000)
'-1,000,000'
>>> FormatWithCommas('%.4f', -1234567.5678)
'-1,234,567.5678'
>>> FormatWithCommas('$%.4f', -1234567.5678)
'$-1,234,567.5678'
"""
parts = re_digits_nondigits.findall(format % (value,))
for i in xrange(len(parts)):
s = parts[i]
if s.isdigit():
parts[i] = _commafy(s)
break
return ''.join(parts)
def _commafy(s):
r = []
for i, c in enumerate(reversed(s)):
if i and (not (i % 3)):
r.insert(0, ',')
r.insert(0, c)
return ''.join(r)
|
Discussion
The recipe works by adding commas to the first contiguous group of digits. It could fail with some odd-ball format that puts extra digits before the number.


Comments
Another solution. #this solution uses the re module and a single function.
import re def currency(amount): temp = "%.2f" % amount profile=re.compile(r"(\d)(\d\d\d[.,])") while 1: temp, count = re.subn(profile,r"\1,\2",temp) if not count: break return '$'+temp
if __name__ == "__main__": print currency(3458905.54) print currency(-49786002.40)
Using locale. FYI, the reason using locale didn't work is probably because you didn't set the locale first:
Counterintuitive, not well documented, non-Pythonic and just plain sucky, but there you go.
Reverse the digits, add commas after each group of three (except the last), then reverse the result.
Nice and simple, but only works for integers; split on '\.' and rejoin if you have a decimal point.
Here is a solution that does not use a regex:
Neat Luciano. So a full version for 2 decimal place numbers would be:
def splitthousands(s, sep=','):
sign='' rhs='' if s[0]=='-': sign='-' s=s[1:] if s.rfind('.')>0: rhs=s[-3:] s=s[:-3] if len(s) <= 3: return sign+s+rhs return sign+splitthousands(s[:-3], sep) + sep + s[-3:]+rhs
Sign in to comment