5

in my scenario (python 2.7), i have:

str(var)

where var is a variable that sometimes requires thousands separators eg 1,500 but as you can see has been converted to a string (for concatenation purposes).

i would like to be able to print out that variable as a string with thousands separators.

i have read solutions for adding formatting to a number eg:

>>> '{:20,.2}'.format(f)
'18,446,744,073,709,551,616.00'

from https://stackoverflow.com/a/1823189/1063287

but this seems to be applicable just for a number, not for a number that has been converted to a string.

thank you.

edit: for more specific context, here is my implementation scenario:

print 'the cost = $' + str(var1) + '\n'
print 'the cost = $' + str(var2) + '\n'

and i have several 'vars'.

Community
  • 1
  • 1
user1063287
  • 10,265
  • 25
  • 122
  • 218

2 Answers2

8

Do not use str(var) and concatenation, that is what .format() is for. Depending on the type of var pick one of:

'{:,}'.format(var)    # format an integer
'{:,.2f}'.format(var) # format a decimal or float

depending on the type of number you have.

>>> var = 12345678.123
>>> '{:,}'.format(int(var))  # ignore the `.123` part
'12,345,678'
>>> '{:,.2f}'.format(var)
'12,345,678.12'
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • thank you, my implementation is `print 'the cost = $' + str(var) + '\n'` so in this context how do i apply that logic? thank you. – user1063287 Mar 11 '13 at 18:36
  • 1
    No need to use `str(var)` at all, use `'the cost = ${:,.2f}\n'.format(var)` instead. – Martijn Pieters Mar 11 '13 at 18:51
  • @user1063287: your situation is much simpler, in fact. Do not use string concatenation if string formatting can be used instead. – Martijn Pieters Mar 11 '13 at 18:53
  • thank you very much, i will use your suggestions, i am getting a large 'indentation' or 'space' before the outputted value when using `print 'the cost = $' + '{:20,}'.format(int(var)) + '\n'` – user1063287 Mar 11 '13 at 19:02
  • @user1063287: You may want to read the [formatting syntax spec](http://docs.python.org/2/library/string.html#format-string-syntax); updated the answer. – Martijn Pieters Mar 11 '13 at 19:04
0

I'm coming very late to this question which I found while looking for a solution for the same thing.

Using the , notation with format() can work very well but poses some problems because unfortunately the , notation can not be applied to strings. So if you are starting with text representations of numbers then you have to convert them to integers or floats before calling format(). The format() code rapidly becomes quite complex if you need to handle both integers and floats with varying levels of precision which need to be preserved. To handle such a situation I ended up writing my own code instead of using format(). It uses the most widely used thousands separator (,) and decimal mark (.) but it could clearly be very quickly modified to work with the notation of other locales or used to create a solution which works for all locales.

def separate_thousands_with_delimiter(num_str):
    """
    Returns a modified version of "num_str" with thousand separators added.
    e.g. "1000000" --> "1,000,000", "1234567.1234567" --> "1,234,567.1234567".
    Numbers which require no thousand separators will be returned unchanged.
    e.g. "123" --> "123", "0.12345" --> "0.12345", ".12345" --> ".12345".
    Signed numbers (a + or - prefix) will be returned with the sign intact.
    e.g. "-12345" --> "-12,345", "+123" --> "+123", "-0.1234" --> "-0.1234".
    """

    decimal_mark = "."
    thousands_delimiter = ","

    sign = ""
    fraction = ""

    # If num_str is signed, store the sign and remove it.
    if num_str[0] == "+" or num_str[0] == "-":
        sign = num_str[0]
        num_str = num_str[1:]

    # If num_str has a decimal mark, store the fraction and remove it.
    # Note that find() will return -1 if the substring is not found.
    dec_mark_pos = num_str.find(decimal_mark)
    if dec_mark_pos >= 0:
        fraction = num_str[dec_mark_pos:]
        num_str = num_str[:dec_mark_pos]

    # Work backwards through num_str inserting a separator after every 3rd digit.
    i = len(num_str) - 3
    while i > 0:
        num_str = num_str[:i] + thousands_delimiter + num_str[i:]
        i -= 3

    # Build and return the final string.
    return sign + num_str + fraction


# Test with:

test_nums = ["1", "10", "100", "1000", "10000", "100000", "1000000",
             "-1", "+10", "-100", "+1000", "-10000", "+100000", "-1000000",
             "1.0", "10.0", "100.0", "1000.0", "10000.0", "100000.0",
             "1000000.0", "1.123456", "10.123456", "100.123456", "1000.123456",
             "10000.123456", "100000.123456", "1000000.123456", "+1.123456",
             "-10.123456", "+100.123456", "-1000.123456", "+10000.123456",
             "-100000.123456", "+1000000.123456", "1234567890123456789",
             "1234567890123456789.1", "-1234567890123456789.1",
             "1234567890123456789.123456789", "0.1", "0.12", "0.123", "0.1234",
             "-0.1", "+0.12", "-0.123", "+0.1234", ".1", ".12", ".123",
             ".1234", "-.1", "+.12", "-.123", "+.1234"]

for num in test_nums:
    print("%s --> %s" % (num, separate_thousands_with_delimiter(num)))


# Beginners should note that an integer or float can be converted to a string
# very easily by simply using: str(int_or_float)

test_int = 1000000
test_int_str = str(test_int)
print("%d --> %s" % (test_int, separate_thousands_with_delimiter(test_int_str)))

test_float = 1000000.1234567
test_float_str = str(test_float)
print("%f --> %s" % (test_float, separate_thousands_with_delimiter(test_float_str)))

Hope this helps. :)

mattst
  • 13,340
  • 4
  • 31
  • 43