Jak przekonwertować ciąg na liczbę, jeśli zawiera przecinki jako separatory tysięcy?

85

Mam ciąg reprezentujący liczbę, która używa przecinków do oddzielenia tysięcy. Jak mogę przekonwertować to na liczbę w Pythonie?

>>> int("1,000,000")

Generuje plik ValueError.

Mógłbym zastąpić przecinki pustymi ciągami znaków, zanim spróbuję je przekonwertować, ale jakoś wydaje się to złe. Czy jest lepszy sposób?

dsimard
źródło

Odpowiedzi:

103
import locale
locale.setlocale( locale.LC_ALL, 'en_US.UTF-8' ) 
locale.atoi('1,000,000')
# 1000000
locale.atof('1,000,000.53')
# 1000000.53
unutbu
źródło
9
+1, ale proszę dodać ustawienie regionalne (przy domyślnym ustawieniu regionalnym 'C'nadal dałoby to ValueError!).
Alex Martelli
1
Myślę, że guru oznacza coś takiego: locale.setlocale (locale.LC_ALL, 'en_US.UTF-8')
mbarkhau
Dzięki za komentarze. Dodałem określone ustawienie regionalne.
unutbu
Bardzo dobrze. W ten sposób radzę sobie z liczbami europejskimi, w których przecinki i kropki również są zamienione. Dzięki.
dsimard
5
Otrzymuję błąd lokalny:Traceback (most recent call last): File "F:\test\locale_num.py", line 2, in <module> locale.setlocale( locale.LC_ALL, 'en_US.UTF-8' ) File "F:\Python27\lib\locale.py", line 539, in setlocale return _setlocale(category, locale) locale.Error: unsupported locale setting
Tony Veijalainen
40

Istnieje kilka sposobów analizowania liczb z separatorami tysięcy. I wątpię, czy sposób opisany przez @unutbu jest najlepszy we wszystkich przypadkach. Dlatego wymieniam też inne sposoby.

  1. Właściwe miejsce do dzwonienia setlocale()to __main__moduł. Jest to ustawienie globalne i będzie miało wpływ na cały program, a nawet rozszerzenia C (chociaż zauważ, że ustawienie LC_NUMERIC nie jest ustawione na poziomie systemu, ale jest emulowane przez Python). Czytać zastrzeżenia w dokumentacji i zastanów się dwa razy, zanim pójdziesz tą drogą. Prawdopodobnie jest OK w pojedynczej aplikacji, ale nigdy nie używaj jej w bibliotekach dla szerokiego grona odbiorców. Prawdopodobnie powinieneś unikać żądania ustawień regionalnych z określonym kodowaniem zestawu znaków, ponieważ może to nie być dostępne w niektórych systemach.

  2. Użyj jednej z bibliotek innych firm do internacjonalizacji. Na przykład PyICU pozwala na użycie dowolnego dostępnego locale bez wpływu na cały proces (a nawet parsowanie liczb z określonymi separatorami tysięcy bez używania ustawień regionalnych):

    NumberFormat.createInstance (Locale ('en_US')). Parse ("1,000,000"). GetLong ()

  3. Napisz własną funkcję parsującą, jeśli nie wiesz, co zainstalować biblioteki innych firm, aby zrobić to „we właściwy sposób”. Może to być tak proste, jak int(data.replace(',', ''))wtedy, gdy ścisła walidacja nie jest potrzebna.

Denis Otkidach
źródło
1
+1 za polecanie w prosty sposób. To wszystko, czego potrzebowałem, kiedy miałem ten sam problem.
Michael Kristofik,
Edytowano, aby poprawić literówkę ( setlocatepowinno być setlocale). Ponadto +1.
Mark Dickinson
Bezwstydna autopromocja, skorzystałem z trzeciej opcji. Więc jeśli ktoś jest zainteresowany, spójrz na to pytanie / odpowiedź
styczeń
14

Zastąp przecinki pustymi ciągami i zamień wynikowy ciąg na intznak lub a float.

>>> a = '1,000,000'
>>> int(a.replace(',' , ''))
1000000
>>> float(a.replace(',' , ''))
1000000.0
Cody Piersall
źródło
21
Przeczytaj ponownie pytanie OP. W szczególności, gdy mówi: „Mógłbym zastąpić przecinki pustymi ciągami znaków, zanim spróbuję je przekonwertować, ale wydaje się to jakoś niewłaściwe. Czy jest lepszy sposób?”
joaquin
1
Uznałem tę odpowiedź za przydatną, biorąc pod uwagę, że mam prawie takie same wymagania jak OP (konwertuj strs na ints), ale cieszę się, że mam prostszy sposób niż zaakceptowana odpowiedź.
Cai
4

To działa:

(Brudny, ale szybki sposób)

>>> a='-1,234,567,89.0123'
>>> "".join(a.split(","))
'-123456789.0123'
Wizmann
źródło
3

Otrzymałem błąd lokalny z zaakceptowanej odpowiedzi, ale następująca zmiana działa tutaj w Finlandii (Windows XP):

import locale
locale.setlocale( locale.LC_ALL, 'english_USA' )
print locale.atoi('1,000,000')
# 1000000
print locale.atof('1,000,000.53')
# 1000000.53
Tony Veijalainen
źródło
1

Próbowałem tego. To wykracza nieco poza pytanie: otrzymujesz wkład. Najpierw zostanie przekonwertowany na ciąg znaków (jeśli jest to lista, na przykład z Beautiful soup); potem do int, a potem do float.

To idzie tak daleko, jak to tylko możliwe. W najgorszym przypadku zwraca wszystko nieprzekonwertowane jako ciąg.

def to_normal(soupCell):
''' converts a html cell from beautiful soup to text, then to int, then to float: as far as it gets.
US thousands separators are taken into account.
needs import locale'''

locale.setlocale( locale.LC_ALL, 'english_USA' ) 

output = unicode(soupCell.findAll(text=True)[0].string)
try: 
    return locale.atoi(output)
except ValueError: 
    try: return locale.atof(output)
    except ValueError:
        return output
Anderas
źródło
0
>>> import locale
>>> locale.setlocale(locale.LC_ALL, "")
'en_US.UTF-8'
>>> print locale.atoi('1,000,000')
1000000
>>> print locale.atof('1,000,000.53')
1000000.53

odbywa się to w systemie Linux w USA.

Jasne
źródło
-1
#python3 tenzin
def changenum(data):
    foo = ""
    for i in list(data):
        if i == ",":
            continue
        else:
            foo += i
    return  float(int(foo))
tintin
źródło
2
Jakieś wyjaśnienie dotyczące tego kodu? Miskę zupy podaje się zwykle z łyżką do zupy
cs95