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?

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

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.


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

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'

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

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

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.


-1
#python3 tenzin
def changenum(data):
    foo = ""
    for i in list(data):
        if i == ",":
            continue
        else:
            foo += i
    return  float(int(foo))

2
Jakieś wyjaśnienie dotyczące tego kodu? Miskę zupy podaje się zwykle z łyżką do zupy
cs95
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.