In Python, what is the simplest way to convert a number enclosed in parentheses (string) to a negative integer (or float)?
For example, '(4,301)' to -4301, as commonly encountered in accounting applications.
In Python, what is the simplest way to convert a number enclosed in parentheses (string) to a negative integer (or float)?
For example, '(4,301)' to -4301, as commonly encountered in accounting applications.
The simplest way is:
my_str = "(4,301)"
num = -int(my_str.translate(None,"(),"))
Since you are reading from a system that put in thousands separators, it's worth mentioning that we are not using them the same way all around the world, which is why you should consider using a locale system. Consider:
import locale
locale.setlocale( locale.LC_ALL, 'en_US.UTF-8' )
my_str = "(4,301)"
result = -locale.atoi(my_str.translate(None,"()"))
Assuming just removing the ,
is safe enough, and you may wish to apply the same function to values that may contain negative numbers or not, then:
import re
print float(re.sub(r'^\((.*?)\)$', r'-\1', a).replace(',',''))
You could then couple that with using locale
as other answers have shown, eg:
import locale, re
locale.setlocale(locale.LC_ALL, 'en_GB.UTF-8')
print locale.atof(re.sub('^\((.*?)\)$', r'-\1', a))
For Python 3.6, and also handles '-' as 0, and strips excess empty spaces:
def clean_num(num_string):
bad_chars = '(),-'
translator = str.maketrans('', '', bad_chars)
clean_digits = num_string.translate(translator).strip()
if clean_digits == '':
return 0
elif '(' in num_string:
return -float(clean_digits)
else:
return float(clean_digits)
Presumably you want to handle positive numbers as well as negative, which is missing from many of the answers thus far. I'm going to add a bit to the answer from mogul.
import locale
locale.setlocale( locale.LC_ALL, '')
my_str = '( 4,301 )'
positive = my_str.translate(None, '()')
result = locale.atoi(positive) if positive == my_str else -locale.atoi(positive)
For localized numbers, I use this:
def clean_number(text):
import locale
locale.setlocale(locale.LC_NUMERIC, "Portuguese_Brazil.1252")
tbl = str.maketrans('(', '-', 'R$ )')
return locale.atof(text.translate(tbl))
Works with Python 3.8. The first parenthesis is replaced with the minus sign, the second is removed. Also removes spaces and the monetary sign.
This code could be a little bit longer, but straight forward and easy to maintain
from pyparsing import Word, nums, OneOrMore
integer = Word(nums)
text = "blah blah (4,301) blah blah "
parser = OneOrMore(integer)
iterator = parser.scanString( text )
try:
while True:
part1 = iterator.next()
part2 = iterator.next()
except:
x = part1[0][0][0] + '.' +part2[0][0][0]
print -float(x)
Produces: -4.301
As of today, the top answer is specific to Python 2. I tried editing it, but the queue is full.
For my_str = "(4,301)"
, the top answer advises:
num = -int(my_str.translate(None,"(),"))
For Python 3, you would instead use one of the following:
translate_table = dict({ord(i): None for i in '(),'})
num = -int(my_str.translate(translate_table))
or, more simply
num = -int(my_str.translate({ord(i): None for i in "(),"}))
If you're curious, the change is necessary for two reasons:
str.translate()
now expects a single argument.
The str
type contains Unicode. This is why each key in the dictionary is first passed to ord
: this function accepts a given Unicode character and returns the Unicode code point for it:
>>> ord('(')
40