Background
I have a list of strings containing numbers. Each string is 8 characters long. For example :
'-123.456'
' -12.345'
' -1.234'
' 123.456'
' 12.345'
' 1.234'
The longest number possible is ' 999.999'
; the smallest number is ' 0.000'
and there always are 3 numbers in the decimal.
What I want to do is compute the opposite of each number, and return it as a string of length 8, with the opposite sign next to the number.
For example :
'-123.456' should yield ' 123.456'
' -12.345' should yield ' 12.345'
' -1.234' should yield ' 1.234'
' 123.456' should yield '-123.456'
' 12.345' should yield ' -12.345'
' 1.234' should yield ' -1.234'
What I did
I wrote the following code, which works :
def opposite(x):
if x.startswith(' -'):
xopp = ' ' + x[3:]
elif x.startswith(' -'):
xopp = ' ' + x[2:]
elif x.startswith('-'):
xopp = ' ' + x[1:]
elif x.startswith(' '):
xopp = ' -' + x[3:]
elif x.startswith(' '):
xopp = ' -' + x[2:]
elif x.startswith(' '):
xopp = '-' + x[1:]
return xopp
My question
I feel like this code is completely "unpythonic" and could be replaced by a one-liner. So the question is: does anyone have an idea to make it more pythonic or even a one-liner ?
3 Answers 3
There are only really two things you need here.
float
. Which allows you to convert the input to a floating point number. If you change to needing more precision or larger numbers,decimal
would be a better choice - thanks @200_success. And,str.format
. Which uses the Format String Syntax. Which you can use pad the left with spaces, so the output has a width of eight.{: >8}
. This however needs to be adjusted for your "there always are 3 numbers in the decimal" requirement, and so you can force this too with{: >8.3f}
.
And so I'd use:
def opposite(x):
return '{: >8.3f}'.format(-float(x))
If however you don't want to use float
then you can use str.lstrip
. With just one if-else:
def opposite(x):
x = x.lstrip()
if x.startswith('-'):
x = x[1:]
else:
x = '-' + x
return '{: >8}'.format(x)
-
\$\begingroup\$ This is perfect. I didn't think of format! This is so simple and yet so beautiful :) Thanks! \$\endgroup\$Luci– Luci2018年02月27日 17:10:45 +00:00Commented Feb 27, 2018 at 17:10
-
2\$\begingroup\$
float
is definitely the least hacks solution. Also considerDecimal
. \$\endgroup\$200_success– 200_success2018年02月27日 17:11:41 +00:00Commented Feb 27, 2018 at 17:11
I usually hang around python 3.x but I don't think there is any way to make it a one-liner due if you put in an "if" statement, you cannot put in another "if" statement due to which "if" statement is the next line talking about.
But as for a more efficient way, possible definitely.
There is definitely a way to make it a one liner, which I will post, nevertheless would be interesting to understand what's happening and how to do it
One liner
return str(-1 * float(x.strip()))
But what's happening?
First, the number you receive contains leading whitespaces, which you want to discard. For that we use the strip function, to get rid of them
x.strip() # For an input of ' -35' will return '-35'
Now, we want to convert the number to float, cause is easier and more verbose to calculate the negative value this way. So we cast to float
float(x.strip())
Then we multiply by -1 to get the opposite
-1 * float(x.strip())
Finally we just need to cast the result to string again, because your function should return a string as you specified
str(-1 * float(x.strip()))
-
1\$\begingroup\$ Unfortunately this won't work as you'll get:
ValueError
:) \$\endgroup\$Grajdeanu Alex– Grajdeanu Alex2018年02月27日 17:06:59 +00:00Commented Feb 27, 2018 at 17:06 -
1\$\begingroup\$ Sorry but this doesn't answer my question : 1. The whole point is to keep the leading spaces to have an 8-characters long string ; 2. Casting to int() won't work, need to use float(). I will update my question to make sure it is understandable that I need to add leading spaces if my string isn't long enough. \$\endgroup\$Luci– Luci2018年02月27日 17:07:01 +00:00Commented Feb 27, 2018 at 17:07
-
\$\begingroup\$ Well, float will do, will amend :) \$\endgroup\$A. Romeu– A. Romeu2018年02月27日 17:12:52 +00:00Commented Feb 27, 2018 at 17:12
Explore related questions
See similar questions with these tags.