# 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

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)

• This is perfect. I didn't think of format! This is so simple and yet so beautiful :) Thanks! – Deuce Feb 27 '18 at 17:10
• float is definitely the least hacks solution. Also consider Decimal. – 200_success Feb 27 '18 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()))

• Unfortunately this won't work as you'll get: ValueError :) – яүυк Feb 27 '18 at 17:06
• 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. – Deuce Feb 27 '18 at 17:07
• Well, float will do, will amend :) – A. Romeu Feb 27 '18 at 17:12