999

Python 2.6.1でカンマを桁区切り記号として整数を出力しようとしています。たとえば、番号1234567を として表示したい1,234,567。どうすればこれを行うことができますか?Google で多くの例を見てきましたが、最も簡単で実用的な方法を探しています。

ピリオドとコンマのどちらを使用するかを決定するのに、ロケール固有である必要はありません。合理的に可能な限りシンプルなものを好むでしょう。

4

29 に答える 29

2125

ロケールに気づかない

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

ロケール認識

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

参照

フォーマット仕様ごとのミニ言語

この','オプションは、千単位の区切り文字にコンマを使用することを示します。ロケール対応の区切り文字の場合は、'n'代わりに整数表示タイプを使用してください。

于 2012-05-24T18:02:17.637 に答える
305

私はこれを機能させました:

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

もちろん、国際化のサポートは必要ありませんが、明確で簡潔で、組み込みのライブラリを使用しています。

PSその「%d」は通常の%スタイルのフォーマッターです。フォーマッタは1つしか持てませんが、フィールド幅と精度設定の点で必要なものなら何でもかまいません。

PPS仕事に取り掛かることができない場合はlocale、マークの回答の修正版をお勧めします。

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)

再帰はネガティブな場合に役立ちますが、コンマごとに1回の再帰は私には少し過剰に思えます。

于 2009-11-30T23:22:13.033 に答える
152

非効率性と読みやすさのために、打ち負かすのは難しいです:

>>> 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('-,','-')
于 2012-01-19T19:35:28.083 に答える
112

無関係な部分を削除し、少しクリーンアップした後のロケール グループ化コードを次に示します。

(以下は整数に対してのみ機能します)

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'

ここにはすでにいくつかの良い答えがあります。今後の参考のためにこれを追加したいだけです。Python 2.7 では、桁区切り記号の書式指定子が導入される予定です。python docsによると、このように機能します

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

Python3.1 では、次のように同じことができます。

>>> format(1234567, ',d')
'1,234,567'
于 2009-11-30T23:42:26.627 に答える
44

1行の正規表現の置換は次のとおりです。

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

負の出力に対してのみ機能します。

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'

または、4 桁未満の float の場合は、書式指定子を次のように変更します%.3f

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

注意:小数部分をグループ化しようとするため、10 進数が 3 桁を超えると正しく機能しません。

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

使い方

それを分解しましょう:

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
于 2012-07-19T13:42:46.690 に答える
13

これには標準ライブラリ関数が必要だと思いますが、再帰を使用して自分で作成するのは楽しかったので、次のように思いつきました。

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)

そうは言っても、他の誰かがそれを行うための標準的な方法を見つけた場合は、代わりにそれを使用する必要があります。

于 2009-11-30T23:19:53.690 に答える
8

コメントからactivestateレシピ498181まで、私はこれを作り直しました:

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

これは、正規表現機能を使用します:先読み、つまり(?=\d)、「後に」数字を持つ 3 桁のグループのみがコンマを取得するようにします。この時点で文字列が逆になっているため、「後」と言います。

[::-1]文字列を逆にするだけです。

于 2010-11-17T15:19:15.540 に答える
8

受け入れられた答えは問題ありませんが、実際にはformat(number,','). 解釈して覚えやすくなりました。

https://docs.python.org/3/library/functions.html#format

于 2017-11-08T22:13:39.370 に答える
6

Python バージョン 2.6 から、これを行うことができます。

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

Python バージョン < 2.6 の場合、参考までに、ここに 2 つの手動の解決策があります。これらは float を int に変換しますが、負の数は正しく機能します。

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)

ここで注意すべき点がいくつかあります:

  • この行: string = '%d' % number数値を文字列に美しく変換し、負数をサポートし、float から分数を削除して int にします。
  • このスライスのindex[::-3]は最後から 3 番目の項目を返すので、別のスライス[1:]を使用して最後の項目を削除しました。最後の番号の後にコンマは必要ありません。
  • この条件付きの l[index] != '-'が負の数をサポートするために使用されている場合、マイナス記号の後にコンマを挿入しないでください。

そして、よりハードコアなバージョン:

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)
于 2016-07-02T04:54:04.127 に答える
1

フロートでも機能するものを次に示します。

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

使用例:

>>> float2comma(10000.1111)
'10,000.111,1'
>>> float2comma(656565.122)
'656,565.122'
>>> float2comma(-656565.122)
'-656,565.122'
于 2010-11-06T13:33:49.993 に答える
1

Python 2.5 を使用しているため、組み込みの書式設定にアクセスできません。

Django コードの intcomma (以下のコードでは intcomma_recurs) を調べたところ、再帰的であり、実行のたびに正規表現をコンパイルするのも良いことではないため、非効率的であることがわかりました。django はこの種の低レベルのパフォーマンスにあまり重点を置いていないため、これは必ずしも「問題」ではありません。また、パフォーマンスに 10 倍の違いがあると予想していましたが、わずか 3 倍遅いだけです。

好奇心から、いくつかのバージョンの intcomma を実装して、正規表現を使用した場合のパフォーマンス上の利点を確認しました。私のテスト データでは、このタスクにはわずかな利点があると結論付けていますが、驚くべきことに、それほど多くはありません。

逆 xrange アプローチを使用することは、正規表現を使用しない場合には不要ですが、コードの見栄えがわずかに向上しますが、パフォーマンスは 10% 程度低下します。

また、渡しているのは文字列であり、数値のように見えると思います。それ以外の場合、結果は未定です。

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

そして、ここにテスト結果があります:

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
于 2012-06-22T02:04:21.353 に答える
0

これはカンマと一緒にお金を稼ぎます

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)
于 2013-12-08T19:51:03.710 に答える
0

浮動小数点数で区切り記号と小数を一緒に使用する: (この例では、小数点以下 2 桁)

large_number = 4545454.26262666
print(f"Formatted: {large_number:,.2f}")

結果: フォーマット済み: 4,545,454.26

于 2021-05-21T17:28:56.960 に答える
-1

整数に対して機能するジェネレーター関数を使用した別のバリアントを次に示します。

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)]))

そして、ここにテストがあります:

>>> 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
于 2012-10-04T17:53:00.913 に答える
-2

サブクラス化するだけですlong(またはfloat、または何でも)。これは非常に実用的です。この方法では、数学演算 (したがって既存のコード) で数値を引き続き使用できますが、端末ではすべて適切に出力されます。

>>> 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
于 2009-11-30T23:25:23.963 に答える
-8

フロートの場合:

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

int の場合:

int(filter(lambda x: x!=',', '1,234'))
# returns 1234
于 2011-12-20T05:03:21.120 に答える