У меня есть несколько строк, представляющих числа с определенным валютным форматом, например:
money="$6,150,593.22"
Я хочу преобразовать эту строку в число
6150593.22
Каков наилучший способ достичь этого?
У меня есть несколько строк, представляющих числа с определенным валютным форматом, например:
money="$6,150,593.22"
Я хочу преобразовать эту строку в число
6150593.22
Каков наилучший способ достичь этого?
Попробуйте следующее:
from re import sub
from decimal import Decimal
money = '$6,150,593.22'
value = Decimal(sub(r'[^\d.]', '', money))
У этого есть некоторые преимущества, поскольку он использует Decimal
вместо float
(что лучше для представления валюты), а также избегает любых проблем с локальностью, -кодирование определенного символа валюты.
Если ваш языковой стандарт установлен правильно, вы можете использовать locale.atof
, но вам все равно придется вручную отключить '$':
>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF8')
'en_US.UTF8'
>>> money = "$6,150,593.22"
>>> locale.atof(money.strip("$"))
6150593.2199999997
Расширение для включения отрицательных чисел в скобки:
In [1]: import locale, string
In [2]: from decimal import Decimal
In [3]: n = ['$1,234.56','-$1,234.56','($1,234.56)', '$ -1,234.56']
In [4]: tbl = string.maketrans('(','-')
In [5]: %timeit -n10000 [locale.atof( x.translate(tbl, '$)')) for x in n]
10000 loops, best of 3: 31.9 æs per loop
In [6]: %timeit -n10000 [Decimal( x.translate(tbl, '$,)')) for x in n]
10000 loops, best of 3: 21 æs per loop
In [7]: %timeit -n10000 [float( x.replace('(','-').translate(None, '$,)')) for x in n]
10000 loops, best of 3: 3.49 æs per loop
In [8]: %timeit -n10000 [float( x.translate(tbl, '$,)')) for x in n]
10000 loops, best of 3: 2.19 æs per loop
Обратите внимание, что запятые должны быть удалены из float()/Decimal(). Либо replace(), либо translate() с таблицей перевода можно использовать для преобразования открытия (в -, переводить немного быстрее. Float() быстрее всего в 10-15 раз, но ему не хватает точности и могут возникнуть проблемы с локалью. Decimal ( ) имеет точность и на 50% быстрее, чем locale.atof(), но также имеет проблемы с локалью. locale.atof() - самый медленный, но самый общий.
Изменение: новый API-интерфейс str.translate
In [1]: import locale, string
from decimal import Decimal
locale.setlocale(locale.LC_ALL, '')
n = ['$1,234.56','-$1,234.56','($1,234.56)', '$ -1,234.56']
In [2]: tbl = str.maketrans('(', '-', '$)')
%timeit -n10000 [locale.atof( x.translate(tbl)) for x in n]
18 µs ± 296 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [3]: tbl2 = str.maketrans('(', '-', '$,)')
%timeit -n10000 [Decimal( x.translate(tbl2)) for x in n]
3.77 µs ± 50.8 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [4]: %timeit -n10000 [float( x.translate(tbl2)) for x in n]
3.13 µs ± 66.3 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [5]: tbl3 = str.maketrans('', '', '$,)')
%timeit -n10000 [float( x.replace('(','-').translate(tbl3)) for x in n]
3.51 µs ± 84.8 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Для решения без жесткого кодирования позиция или символ валюты:
raw_price = "17,30 €"
import locale
locale.setlocale(locale.LC_ALL, 'fr_FR.UTF8')
conv = locale.localeconv()
raw_numbers = raw_price.strip(conv['currency_symbol'].decode('utf-8'))
amount = locale.atof(raw_numbers)
Я нашел пакет babel
очень полезным для обхода
Это позволяет легко разобрать число в локализованном представлении:
>>> babel.numbers.parse_decimal('1,024.64', locale='en')
Decimal('1024.64')
>>> babel.numbers.parse_decimal('1.024,64', locale='de')
Decimal('1024.64')
>>>
Вы можете использовать babel.numbers.get_currency_symbol('USD')
чтобы удалить пре/суффиксы без их babel.numbers.get_currency_symbol('USD')
.
Hth, DTK
Я сделал эту функцию несколько лет назад, чтобы решить ту же проблему.
def money(number):
number = number.strip('$')
try:
[num,dec]=number.rsplit('.')
dec = int(dec)
aside = str(dec)
x = int('1'+'0'*len(aside))
price = float(dec)/x
num = num.replace(',','')
num = int(num)
price = num + price
except:
price = int(number)
return price