I was working on a little Python challenge that was a bit more difficult than expected: format any non-negative number so 1000
turns into "1,000"
, 10000000
into "10,000,000"
and so forth. I managed to do it, but I find my solution not very readable:
def formatting(n):
m = str(n) # Turn it into string
m2 = [] # Empty list that will have the split version of the final number
for i in range(0,len(m),3): # Iterate every three elements
m2.append(m[::-1][i:i+3][::-1]) # Append last three numbers, second to last three numbers, etc.
m2.append(',') # Add a comma between loops
m3 = ''.join(m2[::-1])[1:] # Join and drop the first element which is always a comma.
return m3
This works but it isn't as nice as it could be. What can be done?
1 Answer 1
A few points:
Reversing the string
m
multiple times is unnecessary. Slicing can be done on the original string using correct indices.m[::-1][i:i+3][::-1]
is equivalent tom[-i-3:len(m)-i]
. Another approach is to traverse the indices in the reverse orderfor i in range(len(m)-1, -1, -3)
and then perform slicing accordingly.The logic can be simplified using
str.join
.m2.append(',')
can be omitted. And you can just dom3 = ','.join(m2[::-1])
Further improvements can be achieved by using list comprehensions and traversing the string from the beginning rather than in the reverse order. Some calculation for the indices are needed:
def formatting(n): m = str(n) # Turn it into string num_digits = len(m) seg1_len = (num_digits % 3) or 3 # Calculate length of the first segment segments = [m[:seg1_len], *(m[i:i+3] for i in range(seg1_len, num_digits, 3))] return ','.join(segments)
Python 3's built-in formatting specification actually supports the thousands separator. So you can just do this to achieve the same functionality:
formatted_n = f"{n:,}"
Or equivalently:
formatted_n = "{:,}".format(n)
-
\$\begingroup\$ Thanks! That was quite insightful! Also didn't know about that formatting option. Would have saved me of using
locale
multiple times. \$\endgroup\$Juan C– Juan C2019年09月24日 20:25:16 +00:00Commented Sep 24, 2019 at 20:25 -
\$\begingroup\$ I'm not sure what you used
locale
for. According to the doc, For a locale aware separator, use the 'n' integer presentation type instead. \$\endgroup\$GZ0– GZ02019年09月24日 20:28:38 +00:00Commented Sep 24, 2019 at 20:28 -
\$\begingroup\$ When I'm working with money data that I have to format in some specific currency, but that's totally outside the scope of this \$\endgroup\$Juan C– Juan C2019年09月24日 20:45:26 +00:00Commented Sep 24, 2019 at 20:45
Explore related questions
See similar questions with these tags.
m = str(m)
bem = str(n)
? \$\endgroup\$