Wie drucke ich Zahlen mit Kommas als Tausendertrennzeichen?


754

Ich versuche, eine Ganzzahl in Python 2.6.1 mit Kommas als Tausendertrennzeichen zu drucken . Zum Beispiel möchte ich die Nummer 1234567als anzeigen 1,234,567. Wie würde ich das machen? Ich habe viele Beispiele bei Google gesehen, suche aber nach dem einfachsten praktischen Weg.

Es muss nicht länderspezifisch sein, um zwischen Punkten und Kommas zu entscheiden. Ich würde etwas so Einfaches wie vernünftig bevorzugen.

Antworten:


1739

Gebietsschema ahnungslos

'{:,}'.format(value)  # For Python ≥2.7
f'{value:,}'  # For Python ≥3.6

Gebietsschema bewusst

import locale
locale.setlocale(locale.LC_ALL, '')  # Use '' for auto, or force e.g. to 'en_US.UTF-8'

'{:n}'.format(value)  # For Python ≥2.7
f'{value:n}'  # For Python ≥3.6

Referenz

Pro Formatspezifikation Mini-Sprache ,

Die ','Option signalisiert die Verwendung eines Kommas für ein Tausendertrennzeichen. Verwenden Sie für ein Gebietsschema-fähiges Trennzeichen 'n'stattdessen den ganzzahligen Präsentationstyp.


24
Beachten Sie, dass dies außerhalb der USA und an wenigen anderen Orten nicht korrekt ist. In diesem Fall ist das ausgewählte locale.format () die richtige Antwort.
Gringo Suave

11
Das Schlüsselwort Argument Form:{val:,}.format(val=val)
CivFan

11
Vielen Dank. Für Geldbeträge mit 2 Dezimalstellen - "{:,. 2f}". Format (Wert)
dlink

3
für Portugal, wo wir den Punkt (.) nur als Trennzeichen verwenden: {:,} ". format (value) .replace (',', '.')

13
In Python 3.6 und höher bieten F-Strings noch mehr Komfort. ZBf"{2 ** 64 - 1:,}"
CJ Gaconnet

285

Ich habe das zum Laufen gebracht:

>>> import locale
>>> locale.setlocale(locale.LC_ALL, 'en_US')
'en_US'
>>> locale.format("%d", 1255000, grouping=True)
'1,255,000'

Sicher, die Sie nicht brauchen Unterstützung für Internationalisierung, aber es ist klar, präzise und verwendet eine integrierte Bibliothek.

PS Das "% d" ist der übliche Formatierer im% -Stil. Sie können nur einen Formatierer haben, aber es kann alles sein, was Sie in Bezug auf Feldbreite und Präzisionseinstellungen benötigen.

PPS Wenn Sie nicht bekommen können locale zur Arbeit kommen können, würde ich eine modifizierte Version von Marks Antwort vorschlagen:

def intWithCommas(x):
    if type(x) not in [type(0), type(0L)]:
        raise TypeError("Parameter must be an integer.")
    if x < 0:
        return '-' + intWithCommas(-x)
    result = ''
    while x >= 1000:
        x, r = divmod(x, 1000)
        result = ",%03d%s" % (r, result)
    return "%d%s" % (x, result)

Rekursion ist nützlich für den negativen Fall, aber eine Rekursion pro Komma scheint mir etwas übertrieben.


14
Ich habe Ihren Code ausprobiert und erhalte leider Folgendes: "locale.Error: nicht unterstützte Gebietsschemaeinstellung". : -s
Mark Byers

11
Mark: Wenn Sie unter Linux arbeiten, sollten Sie sich ansehen, was sich in Ihrer Datei /etc/locale.gen befindet oder was auch immer Ihr glibc zum Erstellen seiner Gebietsschemas verwendet. Vielleicht möchten Sie auch "" en "," en_US.utf8 "," en_US.UTF-8 ", 'en_UK" (sp?) Usw. versuchen. Mikez: Es muss ein Buch geben: "Dr. PEP: Or. En Wie ich gelernt habe, mich nicht mehr zu sorgen und zu lieben docs.python.org. " Ich habe es aufgegeben, alle Bibliotheken rund um Python 1.5.6 auswendig zu lernen. Was localeverwende ich so wenig wie ich kann.
Mike DeSimone

10
Sie können '' verwenden setlocale, um die Standardeinstellung zu verwenden, die hoffentlich angemessen ist.
Mark Ransom

24
Versuchen Sie Folgendes: locale.setlocale (locale.LC_ALL, '') Es hat bei mir funktioniert
Nadia Alramli

1
Obwohl klug, mag ich keine Funktionen, die globale Einstellungen vornehmen ... Die Verwendung von 'blah'.format () ist der bessere Weg.
Cerin

132

Für Ineffizienz und Unlesbarkeit ist es schwer zu schlagen:

>>> import itertools
>>> s = '-1234567'
>>> ','.join(["%s%s%s" % (x[0], x[1] or '', x[2] or '') for x in itertools.izip_longest(s[::-1][::3], s[::-1][1::3], s[::-1][2::3])])[::-1].replace('-,','-')

171
Gewählt für die ineffizienteste und unlesbarste Methode zur Beantwortung dieser Frage.
Psytek

1
wäre schön wenn das zumindest klappen würde. versuchen Sie diese Nummer "17371830" es wird "173.718.3.0" =)
Holms

5
Perioden? Das ist nicht mal möglich, Holms. Dieses Stück Müll ignoriert das Gebietsschema völlig. Ich frage mich, wie Sie zu diesem Ergebnis gekommen sind. Ihr Beispiel ergibt für mich erwartungsgemäß '17, 371.830 '.
Kasey Kirkham

11
Um dies zu einer Funktion zu machen, würde ich vorschlagen: lambda x: (lambda s: ','.join(["%s%s%s" % (x[0], x[1] or '', x[2] or '') for x in itertools.izip_longest(s[::-1][::3], s[::-1][1::3], s[::-1][2::3])])[::-1].replace('-,','-'))(str(x))nur um das Verschleierungsthema beizubehalten.
Quanten

95

Hier ist der Gruppierungscode für das Gebietsschema, nachdem irrelevante Teile entfernt und ein wenig aufgeräumt wurden:

(Das Folgende funktioniert nur für ganze Zahlen)

def group(number):
    s = '%d' % number
    groups = []
    while s and s[-1].isdigit():
        groups.append(s[-3:])
        s = s[:-3]
    return s + ','.join(reversed(groups))

>>> group(-23432432434.34)
'-23,432,432,434'

Hier gibt es bereits einige gute Antworten. Ich möchte dies nur zum späteren Nachschlagen hinzufügen. In Python 2.7 wird es einen Formatbezeichner für das Tausendertrennzeichen geben. Laut Python-Dokumenten funktioniert es so

>>> '{:20,.2f}'.format(f)
'18,446,744,073,709,551,616.00'

In python3.1 können Sie dasselbe wie folgt tun:

>>> format(1234567, ',d')
'1,234,567'

Ja, die schwierigeren Wege sind hauptsächlich für Leute mit älteren Pythons, wie die, die mit RHEL und anderen Distributionen mit langfristiger Unterstützung ausgeliefert werden.
Mike DeSimone

3
Wie kann man dies mit Formatzeichenfolgen ausdrücken? "%, d"% 1234567 funktioniert nicht
Frederic Bazin

92

Ich bin überrascht, dass niemand erwähnt hat, dass Sie dies mit f-Strings in Python 3.6 so einfach machen können:

>>> num = 10000000
>>> print(f"{num:,}")
10,000,000

... wobei der Teil nach dem Doppelpunkt der Formatbezeichner ist. Das Komma ist das gewünschte Trennzeichenf"{num:_}" verwendet also Unterstriche anstelle eines Kommas.

Dies entspricht der Verwendung format(num, ",")für ältere Versionen von Python 3.


39

Hier ist ein einzeiliger Regex-Ersatz:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)

Funktioniert nur für integrierte Ausgaben:

import re
val = 1234567890
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)
# Returns: '1,234,567,890'

val = 1234567890.1234567890
# Returns: '1,234,567,890'

Oder ändern Sie für Floats mit weniger als 4 Ziffern den Formatbezeichner in %.3f:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.3f" % val)
# Returns: '1,234,567,890.123'

NB: Funktioniert nicht korrekt mit mehr als drei Dezimalstellen, da versucht wird, den Dezimalteil zu gruppieren:

re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.5f" % val)
# Returns: '1,234,567,890.12,346'

Wie es funktioniert

Lassen Sie es uns zusammenfassen:

re.sub(pattern, repl, string)

pattern = \
    "(\d)           # Find one digit...
     (?=            # that is followed by...
         (\d{3})+   # one or more groups of three digits...
         (?!\d)     # which are not followed by any more digits.
     )",

repl = \
    r"\1,",         # Replace that one digit by itself, followed by a comma,
                    # and continue looking for more matches later in the string.
                    # (re.sub() replaces all matches it finds in the input)

string = \
    "%d" % val      # Format the string as a decimal to begin with

1
Verwenden Sie den ausführlichen Modus und Sie können Kommentare direkt im Code haben
Daniel Stracaboško

Könnten Sie das "(?! \ D)" nicht durch ein "$" ersetzen?
GL2014

28

Das mache ich für Schwimmer. Obwohl ich ehrlich gesagt nicht sicher bin, für welche Versionen es funktioniert - ich verwende 2.7:

my_number = 4385893.382939491

my_string = '{:0,.2f}'.format(my_number)

Rückgabe: 4.385.893,38

Update: Ich hatte kürzlich ein Problem mit diesem Format (ich konnte Ihnen den genauen Grund nicht nennen), konnte es jedoch beheben, indem ich das löschte 0 :

my_string = '{:,.2f}'.format(my_number)

19

Sie können auch verwenden '{:n}'.format( value ) eine Gebietsschemadarstellung verwenden. Ich denke, dies ist der einfachste Weg für eine Gebietsschema-Lösung.

Weitere Informationen finden Sie thousandsin Python DOC .

Für die Währung können Sie locale.currencydas Flag setzengrouping :

Code

import locale

locale.setlocale( locale.LC_ALL, '' )
locale.currency( 1234567.89, grouping = True )

Ausgabe

'Portuguese_Brazil.1252'
'R$ 1.234.567,89'

13

Die Antwort von Ian Schneider leicht erweitern:

Wenn Sie ein benutzerdefiniertes Tausendertrennzeichen verwenden möchten, ist die einfachste Lösung:

'{:,}'.format(value).replace(',', your_custom_thousands_separator)

Beispiele

'{:,.2f}'.format(123456789.012345).replace(',', ' ')

Wenn Sie die deutsche Darstellung so wollen, wird es etwas komplizierter:

('{:,.2f}'.format(123456789.012345)
          .replace(',', ' ')  # 'save' the thousands separators 
          .replace('.', ',')  # dot to comma
          .replace(' ', '.')) # thousand separators to dot

Etwas kürzer:'{:_.2f}'.format(12345.6789).replace('.', ',').replace('_', '.')
Tom Pohl

12

Ich bin mir sicher, dass es dafür eine Standardbibliotheksfunktion geben muss, aber es hat Spaß gemacht, sie selbst mithilfe der Rekursion zu schreiben. Deshalb habe ich mir Folgendes ausgedacht:

def intToStringWithCommas(x):
    if type(x) is not int and type(x) is not long:
        raise TypeError("Not an integer!")
    if x < 0:
        return '-' + intToStringWithCommas(-x)
    elif x < 1000:
        return str(x)
    else:
        return intToStringWithCommas(x / 1000) + ',' + '%03d' % (x % 1000)

Wenn jedoch jemand anderes einen Standardweg findet, sollten Sie diesen stattdessen verwenden.


Funktioniert leider nicht in allen Fällen. intToStringWithCommas (1000.1) -> '1.0001.000'
Nadia Alramli

Er sagte ausdrücklich Ganzzahlen und dass es so einfach wie möglich sein sollte, also entschied ich mich, keine anderen Datentypen als Ganzzahlen zu behandeln. Ich habe es auch im Funktionsnamen _int_ToStringWithCommas explizit gemacht. Jetzt habe ich auch eine Erhöhung hinzugefügt, um es klarer zu machen.
Mark Byers

8

Aus den Kommentaren zum Aktivierungsrezept 498181 habe ich Folgendes überarbeitet:

import re
def thous(x, sep=',', dot='.'):
    num, _, frac = str(x).partition(dot)
    num = re.sub(r'(\d{3})(?=\d)', r'\1'+sep, num[::-1])[::-1]
    if frac:
        num += dot + frac
    return num

Es verwendet die Funktion für reguläre Ausdrücke: Lookahead, dh (?=\d)um sicherzustellen, dass nur Gruppen mit drei Ziffern, die eine Ziffer 'nach' haben, ein Komma erhalten. Ich sage 'nach', weil die Zeichenfolge an dieser Stelle umgekehrt ist.

[::-1] kehrt einfach eine Zeichenfolge um.



7

Python 3

- -

Ganzzahlen (ohne Dezimalzahl):

"{:,d}".format(1234567)

- -

Floats (mit Dezimalzahl):

"{:,.2f}".format(1234567)

Dabei fgibt die vorherige Zahl die Anzahl der Dezimalstellen an.

- -

Bonus

Schnellstartfunktion für das indische Lakhs / Crores-Nummerierungssystem (12,34,567):

https://stackoverflow.com/a/44832241/4928578


5

Ab Python Version 2.6 können Sie dies tun:

def format_builtin(n):
    return format(n, ',')

Für Python-Versionen <2.6 und nur zu Ihrer Information, hier sind 2 manuelle Lösungen, die Floats in Ints umwandeln, aber negative Zahlen funktionieren korrekt:

def format_number_using_lists(number):
    string = '%d' % number
    result_list = list(string)
    indexes = range(len(string))
    for index in indexes[::-3][1:]:
        if result_list[index] != '-':
            result_list.insert(index+1, ',')
    return ''.join(result_list)

Einige Dinge, die hier zu beachten sind:

  • diese Zeile: string = '% d'% number konvertiert eine wunderschön in eine Zeichenfolge, unterstützt Negative und löscht Brüche aus Floats, wodurch sie zu Ints werden.
  • Dieser Slice- Index [:: - 3] gibt jedes dritte Element ab dem Ende zurück . Daher habe ich ein weiteres Slice [1:] verwendet , um das allerletzte Element zu entfernen, da ich nach der letzten Nummer kein Komma benötige.
  • Diese Bedingung, wenn l [index]! = '-' zur Unterstützung negativer Zahlen verwendet wird, fügen Sie nach dem Minuszeichen kein Komma ein.

Und eine Hardcore-Version:

def format_number_using_generators_and_list_comprehensions(number):
    string = '%d' % number
    generator = reversed( 
        [
            value+',' if (index!=0 and value!='-' and index%3==0) else value
            for index,value in enumerate(reversed(string))
        ]
    )
    return ''.join(generator)

2

Ich bin ein Python-Anfänger, aber ein erfahrener Programmierer. Ich habe Python 3.5, daher kann ich nur das Komma verwenden, aber dies ist dennoch eine interessante Programmierübung. Betrachten Sie den Fall einer vorzeichenlosen Ganzzahl. Das am besten lesbare Python-Programm zum Hinzufügen von Tausenden Trennzeichen scheint zu sein:

def add_commas(instr):
    out = [instr[0]]
    for i in range(1, len(instr)):
        if (len(instr) - i) % 3 == 0:
            out.append(',')
        out.append(instr[i])
    return ''.join(out)

Es ist auch möglich, ein Listenverständnis zu verwenden:

add_commas(instr):
    rng = reversed(range(1, len(instr) + (len(instr) - 1)//3 + 1))
    out = [',' if j%4 == 0 else instr[-(j - j//4)] for j in rng]
    return ''.join(out)

Dies ist kürzer und könnte ein Einzeiler sein, aber Sie müssen einige mentale Gymnastik machen, um zu verstehen, warum es funktioniert. In beiden Fällen erhalten wir:

for i in range(1, 11):
    instr = '1234567890'[:i]
    print(instr, add_commas(instr))
1 1
12 12
123 123
1234 1,234
12345 12,345
123456 123,456
1234567 1,234,567
12345678 12,345,678
123456789 123,456,789
1234567890 1,234,567,890

Die erste Version ist die sinnvollere Wahl, wenn Sie möchten, dass das Programm verstanden wird.


1

Hier ist eine, die auch für Schwimmer funktioniert:

def float2comma(f):
    s = str(abs(f)) # Convert to a string
    decimalposition = s.find(".") # Look for decimal point
    if decimalposition == -1:
        decimalposition = len(s) # If no decimal, then just work from the end
    out = "" 
    for i in range(decimalposition+1, len(s)): # do the decimal
        if not (i-decimalposition-1) % 3 and i-decimalposition-1: out = out+","
        out = out+s[i]      
    if len(out):
        out = "."+out # add the decimal point if necessary
    for i in range(decimalposition-1,-1,-1): # working backwards from decimal point
        if not (decimalposition-i-1) % 3 and decimalposition-i-1: out = ","+out
        out = s[i]+out      
    if f < 0:
        out = "-"+out
    return out

Anwendungsbeispiel:

>>> float2comma(10000.1111)
'10,000.111,1'
>>> float2comma(656565.122)
'656,565.122'
>>> float2comma(-656565.122)
'-656,565.122'

1
float2comma(12031023.1323)Rückgabe: '12, 031,023.132,3 '
Demux

1

Ein Liner für Python 2.5+ und Python 3 (nur positiv int):

''.join(reversed([x + (',' if i and not i % 3 else '') for i, x in enumerate(reversed(str(1234567)))]))

1

Universelle Lösung

Ich habe einige Probleme mit dem Punkttrennzeichen in den vorherigen Antworten gefunden. Ich habe eine universelle Lösung entwickelt, bei der Sie alles, was Sie wollen, als Tausendertrennzeichen verwenden können, ohne das Gebietsschema zu ändern . Ich weiß, dass es nicht die eleganteste Lösung ist, aber es erledigt den Job. Fühlen Sie sich frei, es zu verbessern!

def format_integer(number, thousand_separator='.'):
    def reverse(string):
        string = "".join(reversed(string))
        return string

    s = reverse(str(number))
    count = 0
    result = ''
    for char in s:
        count = count + 1
        if count % 3 == 0:
            if len(s) == count:
                result = char + result
            else:
                result = thousand_separator + char + result
        else:
            result = char + result
    return result


print(format_integer(50))
# 50
print(format_integer(500))
# 500
print(format_integer(50000))
# 50.000
print(format_integer(50000000))
# 50.000.000

0

Dies macht Geld zusammen mit den Kommas

def format_money(money, presym='$', postsym=''):
    fmt = '%0.2f' % money
    dot = string.find(fmt, '.')
    ret = []
    if money < 0 :
        ret.append('(')
        p0 = 1
    else :
        p0 = 0
    ret.append(presym)
    p1 = (dot-p0) % 3 + p0
    while True :
        ret.append(fmt[p0:p1])
        if p1 == dot : break
        ret.append(',')
        p0 = p1
        p1 += 3
    ret.append(fmt[dot:])   # decimals
    ret.append(postsym)
    if money < 0 : ret.append(')')
    return ''.join(ret)

0

Ich habe eine Python 2 und Python 3 Version dieses Codes. Ich weiß, dass die Frage für Python 2 gestellt wurde, aber jetzt (8 Jahre später lol) werden die Leute wahrscheinlich Python 3 verwenden.

Python 3-Code:

import random
number = str(random.randint(1, 10000000))
comma_placement = 4
print('The original number is: {}. '.format(number))
while True:
    if len(number) % 3 == 0:
        for i in range(0, len(number) // 3 - 1):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
            comma_placement = comma_placement + 4
    else:
        for i in range(0, len(number) // 3):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
    break
print('The new and improved number is: {}'.format(number))        


Python 2-Code: (Bearbeiten. Der Python 2-Code funktioniert nicht. Ich denke, dass die Syntax anders ist.)

import random
number = str(random.randint(1, 10000000))
comma_placement = 4
print 'The original number is: %s.' % (number)
while True:
    if len(number) % 3 == 0:
        for i in range(0, len(number) // 3 - 1):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
            comma_placement = comma_placement + 4
    else:
        for i in range(0, len(number) // 3):
            number = number[0:len(number) - comma_placement + 1] + ',' + number[len(number) - comma_placement + 1:]
    break
print 'The new and improved number is: %s.' % (number) 

0

Ich verwende Python 2.5, daher habe ich keinen Zugriff auf die integrierte Formatierung.

Ich habe mir den Django-Code intcomma (intcomma_recurs im Code unten) angesehen und festgestellt, dass er ineffizient ist, da er rekursiv ist und es auch nicht gut ist, den regulären Ausdruck bei jedem Lauf zu kompilieren. Dies ist kein notwendiges Problem, da Django sich nicht wirklich auf diese Art von Leistung auf niedrigem Niveau konzentriert. Außerdem hatte ich einen Faktor von 10 Leistungsunterschieden erwartet, aber es ist nur dreimal langsamer.

Aus Neugier habe ich einige Versionen von intcomma implementiert, um zu sehen, welche Leistungsvorteile bei der Verwendung von Regex bestehen. Meine Testdaten schließen einen kleinen Vorteil für diese Aufgabe, aber überraschenderweise überhaupt nicht viel.

Ich war auch erfreut zu sehen, was ich vermutete: Die Verwendung des umgekehrten xrange-Ansatzes ist im Fall ohne Regex nicht erforderlich, lässt den Code jedoch bei Kosten von ~ 10% Leistung etwas besser aussehen.

Außerdem gehe ich davon aus, dass das, was Sie übergeben, eine Zeichenfolge ist und etwas wie eine Zahl aussieht. Ergebnisse ansonsten unbestimmt.

from __future__ import with_statement
from contextlib import contextmanager
import re,time

re_first_num = re.compile(r"\d")
def intcomma_noregex(value):
    end_offset, start_digit, period = len(value),re_first_num.search(value).start(),value.rfind('.')
    if period == -1:
        period=end_offset
    segments,_from_index,leftover = [],0,(period-start_digit) % 3
    for _index in xrange(start_digit+3 if not leftover else start_digit+leftover,period,3):
        segments.append(value[_from_index:_index])
        _from_index=_index
    if not segments:
        return value
    segments.append(value[_from_index:])
    return ','.join(segments)

def intcomma_noregex_reversed(value):
    end_offset, start_digit, period = len(value),re_first_num.search(value).start(),value.rfind('.')
    if period == -1:
        period=end_offset
    _from_index,segments = end_offset,[]
    for _index in xrange(period-3,start_digit,-3):
        segments.append(value[_index:_from_index])
        _from_index=_index
    if not segments:
        return value
    segments.append(value[:_from_index])
    return ','.join(reversed(segments))

re_3digits = re.compile(r'(?<=\d)\d{3}(?!\d)')
def intcomma(value):
    segments,last_endoffset=[],len(value)
    while last_endoffset > 3:
        digit_group = re_3digits.search(value,0,last_endoffset)
        if not digit_group:
            break
        segments.append(value[digit_group.start():last_endoffset])
        last_endoffset=digit_group.start()
    if not segments:
        return value
    if last_endoffset:
        segments.append(value[:last_endoffset])
    return ','.join(reversed(segments))

def intcomma_recurs(value):
    """
    Converts an integer to a string containing commas every three digits.
    For example, 3000 becomes '3,000' and 45000 becomes '45,000'.
    """
    new = re.sub("^(-?\d+)(\d{3})", '\g<1>,\g<2>', str(value))
    if value == new:
        return new
    else:
        return intcomma(new)

@contextmanager
def timed(save_time_func):
    begin=time.time()
    try:
        yield
    finally:
        save_time_func(time.time()-begin)

def testset_xsimple(func):
    func('5')

def testset_simple(func):
    func('567')

def testset_onecomma(func):
    func('567890')

def testset_complex(func):
    func('-1234567.024')

def testset_average(func):
    func('-1234567.024')
    func('567')
    func('5674')

if __name__ == '__main__':
    print 'Test results:'
    for test_data in ('5','567','1234','1234.56','-253892.045'):
        for func in (intcomma,intcomma_noregex,intcomma_noregex_reversed,intcomma_recurs):
            print func.__name__,test_data,func(test_data)
    times=[]
    def overhead(x):
        pass
    for test_run in xrange(1,4):
        for func in (intcomma,intcomma_noregex,intcomma_noregex_reversed,intcomma_recurs,overhead):
            for testset in (testset_xsimple,testset_simple,testset_onecomma,testset_complex,testset_average):
                for x in xrange(1000): # prime the test
                    testset(func)
                with timed(lambda x:times.append(((test_run,func,testset),x))):
                    for x in xrange(50000):
                        testset(func)
    for (test_run,func,testset),_delta in times:
        print test_run,func.__name__,testset.__name__,_delta

Und hier sind die Testergebnisse:

intcomma 5 5
intcomma_noregex 5 5
intcomma_noregex_reversed 5 5
intcomma_recurs 5 5
intcomma 567 567
intcomma_noregex 567 567
intcomma_noregex_reversed 567 567
intcomma_recurs 567 567
intcomma 1234 1,234
intcomma_noregex 1234 1,234
intcomma_noregex_reversed 1234 1,234
intcomma_recurs 1234 1,234
intcomma 1234.56 1,234.56
intcomma_noregex 1234.56 1,234.56
intcomma_noregex_reversed 1234.56 1,234.56
intcomma_recurs 1234.56 1,234.56
intcomma -253892.045 -253,892.045
intcomma_noregex -253892.045 -253,892.045
intcomma_noregex_reversed -253892.045 -253,892.045
intcomma_recurs -253892.045 -253,892.045
1 intcomma testset_xsimple 0.0410001277924
1 intcomma testset_simple 0.0369999408722
1 intcomma testset_onecomma 0.213000059128
1 intcomma testset_complex 0.296000003815
1 intcomma testset_average 0.503000020981
1 intcomma_noregex testset_xsimple 0.134000062943
1 intcomma_noregex testset_simple 0.134999990463
1 intcomma_noregex testset_onecomma 0.190999984741
1 intcomma_noregex testset_complex 0.209000110626
1 intcomma_noregex testset_average 0.513000011444
1 intcomma_noregex_reversed testset_xsimple 0.124000072479
1 intcomma_noregex_reversed testset_simple 0.12700009346
1 intcomma_noregex_reversed testset_onecomma 0.230000019073
1 intcomma_noregex_reversed testset_complex 0.236999988556
1 intcomma_noregex_reversed testset_average 0.56299996376
1 intcomma_recurs testset_xsimple 0.348000049591
1 intcomma_recurs testset_simple 0.34600019455
1 intcomma_recurs testset_onecomma 0.625
1 intcomma_recurs testset_complex 0.773999929428
1 intcomma_recurs testset_average 1.6890001297
1 overhead testset_xsimple 0.0179998874664
1 overhead testset_simple 0.0190000534058
1 overhead testset_onecomma 0.0190000534058
1 overhead testset_complex 0.0190000534058
1 overhead testset_average 0.0309998989105
2 intcomma testset_xsimple 0.0360000133514
2 intcomma testset_simple 0.0369999408722
2 intcomma testset_onecomma 0.207999944687
2 intcomma testset_complex 0.302000045776
2 intcomma testset_average 0.523000001907
2 intcomma_noregex testset_xsimple 0.139999866486
2 intcomma_noregex testset_simple 0.141000032425
2 intcomma_noregex testset_onecomma 0.203999996185
2 intcomma_noregex testset_complex 0.200999975204
2 intcomma_noregex testset_average 0.523000001907
2 intcomma_noregex_reversed testset_xsimple 0.130000114441
2 intcomma_noregex_reversed testset_simple 0.129999876022
2 intcomma_noregex_reversed testset_onecomma 0.236000061035
2 intcomma_noregex_reversed testset_complex 0.241999864578
2 intcomma_noregex_reversed testset_average 0.582999944687
2 intcomma_recurs testset_xsimple 0.351000070572
2 intcomma_recurs testset_simple 0.352999925613
2 intcomma_recurs testset_onecomma 0.648999929428
2 intcomma_recurs testset_complex 0.808000087738
2 intcomma_recurs testset_average 1.81900000572
2 overhead testset_xsimple 0.0189998149872
2 overhead testset_simple 0.0189998149872
2 overhead testset_onecomma 0.0190000534058
2 overhead testset_complex 0.0179998874664
2 overhead testset_average 0.0299999713898
3 intcomma testset_xsimple 0.0360000133514
3 intcomma testset_simple 0.0360000133514
3 intcomma testset_onecomma 0.210000038147
3 intcomma testset_complex 0.305999994278
3 intcomma testset_average 0.493000030518
3 intcomma_noregex testset_xsimple 0.131999969482
3 intcomma_noregex testset_simple 0.136000156403
3 intcomma_noregex testset_onecomma 0.192999839783
3 intcomma_noregex testset_complex 0.202000141144
3 intcomma_noregex testset_average 0.509999990463
3 intcomma_noregex_reversed testset_xsimple 0.125999927521
3 intcomma_noregex_reversed testset_simple 0.126999855042
3 intcomma_noregex_reversed testset_onecomma 0.235999822617
3 intcomma_noregex_reversed testset_complex 0.243000030518
3 intcomma_noregex_reversed testset_average 0.56200003624
3 intcomma_recurs testset_xsimple 0.337000131607
3 intcomma_recurs testset_simple 0.342000007629
3 intcomma_recurs testset_onecomma 0.609999895096
3 intcomma_recurs testset_complex 0.75
3 intcomma_recurs testset_average 1.68300008774
3 overhead testset_xsimple 0.0189998149872
3 overhead testset_simple 0.018000125885
3 overhead testset_onecomma 0.018000125885
3 overhead testset_complex 0.0179998874664
3 overhead testset_average 0.0299999713898

Ich dachte, Daniel Fortunovs One-Regex-Lösung wäre die Nummer 1 und würde alle Algorithmen übertreffen, weil Regex in C so verfeinert / optimiert und codiert ist, aber nein. Ich denke, das Muster und die Lookaheads sind zu teuer. es fällt ungefähr mit der doppelten Zeit des obigen Intcomma ein, selbst wenn der Regex vorkompiliert wird.
Parität3


-1

Hier ist eine andere Variante, die eine Generatorfunktion verwendet, die für ganze Zahlen funktioniert:

def ncomma(num):
    def _helper(num):
        # assert isinstance(numstr, basestring)
        numstr = '%d' % num
        for ii, digit in enumerate(reversed(numstr)):
            if ii and ii % 3 == 0 and digit.isdigit():
                yield ','
            yield digit

    return ''.join(reversed([n for n in _helper(num)]))

Und hier ist ein Test:

>>> for i in (0, 99, 999, 9999, 999999, 1000000, -1, -111, -1111, -111111, -1000000):
...     print i, ncomma(i)
... 
0 0
99 99
999 999
9999 9,999
999999 999,999
1000000 1,000,000
-1 -1
-111 -111
-1111 -1,111
-111111 -111,111
-1000000 -1,000,000

-1

Nur Unterklasse long(oder floatoder was auch immer). Dies ist sehr praktisch, da Sie auf diese Weise Ihre Zahlen weiterhin in Matheoperationen (und damit in vorhandenem Code) verwenden können, sie jedoch alle in Ihrem Terminal gut gedruckt werden.

>>> class number(long):

        def __init__(self, value):
            self = value

        def __repr__(self):
            s = str(self)
            l = [x for x in s if x in '1234567890']
            for x in reversed(range(len(s)-1)[::3]):
                l.insert(-x, ',')
            l = ''.join(l[1:])
            return ('-'+l if self < 0 else l) 

>>> number(-100000)
-100,000
>>> number(-100)
-100
>>> number(-12345)
-12,345
>>> number(928374)
928,374
>>> 345

8
Ich mag die Idee der Unterklasse, aber ist __repr__()die richtige Methode zum Überschreiben? Ich würde vorschlagen , außer Kraft zu setzen __str__()und in __repr__()Ruhe zu lassen, weil int(repr(number(928374)))es funktionieren sollte, aber int()an den Kommas ersticken wird.
Steveha

@steveha hat einen guten Punkt, aber die Rechtfertigung sollte gewesen sein, dass number(repr(number(928374)))nicht funktioniert, nicht int(repr(number(928374))). Damit dieser Ansatz direkt mit printdem OP funktioniert , sollte die __str__()Methode eher überschrieben als überschrieben werden __repr__(). Unabhängig davon scheint es einen Fehler in der Logik zum Einfügen von Kommas zu geben.
Martineau

-1

Italien:

>>> import locale
>>> locale.setlocale(locale.LC_ALL,"")
'Italian_Italy.1252'
>>> f"{1000:n}"
'1.000'

-8

Für Schwimmer:

float(filter(lambda x: x!=',', '1,234.52'))
# returns 1234.52

Für Ints:

int(filter(lambda x: x!=',', '1,234'))
# returns 1234

5
Das entfernt die Kommas. Das OP war zwar praktisch, fragte aber nach einer Möglichkeit, sie hinzuzufügen . Außerdem float('1,234.52'.translate(None, ','))könnte so etwas einfacher und möglicherweise schneller sein.
Bis auf weiteres angehalten.
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.