Як надрукувати число комами у вигляді тисяч роздільників?


752

Я намагаюся надрукувати ціле число в Python 2.6.1 комами як тисячі роздільників. Наприклад, я хочу показати число 1234567як 1,234,567. Як би я пішов робити це? Я бачив багато прикладів в Google, але шукаю найпростіший практичний спосіб.

Не потрібно визначати локаль для визначення періодів і коми. Я вважаю за краще щось просте, наскільки розумно можливо.

Відповіді:


1737

Про місцеві відомості

'{:,}'.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

Довідково

Per Format Specification Mini-Language ,

','Варіант сигналізує використання коми для роздільник тисяч. Для відокремлювача локальної мови 'n'замість цього використовуйте цілий тип презентації.


24
Зауважте, що це не буде правильним за межами США та декількох інших місць, у такому випадку вибраний locale.format () - правильна відповідь.
Gringo Suave

10
Форма аргументу ключового слова:{val:,}.format(val=val)
CivFan

11
Щиро дякую. Для грошових сум з двома
знаками

3
для Португалії, де ми використовуємо точку (.) як роздільник просто: {:,} ". format (value) .replace (',', '.')

13
У python 3.6 і вище, f-рядки додають ще більшої зручності. Напр.f"{2 ** 64 - 1:,}"
CJ Gaconnet

285

У мене це працює:

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

Звичайно, вам не потрібна підтримка інтернаціоналізації, але вона чітка, стисла і використовує вбудовану бібліотеку.

PS Що "% d" - це звичайний формат% -style. Ви можете мати лише один формат, але це може бути все, що вам потрібно з точки зору ширини поля та налаштувань точності.

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)

Рекурсія корисна для негативного випадку, але одна рекурсія за комою здається мені трохи надмірною.


14
Я спробував ваш код, і, на жаль, я отримую це: "locale.Error: непідтримувані налаштування локалі". : -s
Марк Байєрс

11
Позначення: Якщо ви працюєте в Linux, ви можете подивитися, що знаходиться у вашому /etc/locale.gen, або що б ваш glibc використовував для створення своїх локальних файлів. Ви також можете спробувати "" en "," en_US.utf8 "," en_US.UTF-8 "," en_UK "(sp?) І т. Д. Mikez: Там повинна бути книга:" Dr. PEP: Або Як я навчився переставати хвилюватися і любити docs.python.org ". Я відмовився запам'ятовувати всі бібліотеки ще навколо Python 1.5.6. Що стосується locale, я використовую її якомога менше.
Майк Десимоне

10
Ви можете використовувати "" для setlocaleвикористання за замовчуванням, що, сподіваємось, буде доречним.
Марк Викуп

24
Спробуйте це: locale.setlocale (locale.LC_ALL, '') Це працювало для мене
Надія Алрамлі

1
Хоча розумний, мені не подобаються функції, які роблять глобальні налаштування ... Використання 'blah'.format () - це кращий шлях.
Серін

132

Для неефективності та нечитабельності важко перемогти:

>>> 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
Голосували за найефективніший і нечитабельний метод відповіді на це питання.
psytek

1
Було б добре, якби це хоча б спрацювало. спробуйте це число "17371830", воно стає "173.718.3.0" =)
затихає

5
Періоди? Це навіть неможливо, кумед. Цей шматок мотлоху повністю ігнорує місцевість. Цікаво, як ти отримав такий результат. Ваш приклад дає "17, 371,830" для мене, як і очікувалося.
Kasey Kirkham

11
Щоб зробити це функцією, я б запропонував: 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))просто зберегти тему притуплення.
квантовий

95

Ось код групування локалів після видалення невідповідних частин та їх невеликого очищення:

(Наступне працює лише для цілих чисел)

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, це працює так

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

У python3.1 ви можете зробити те саме, що і це:

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

Так, найскладніші способи в основному стосуються людей на старих пітонах, таких як ті, що поставляються з RHEL та іншими довгостроковими дистрибутивами підтримки.
Майк Десімоне

3
як це виразити за допомогою рядків формату? "%, d"% 1234567 не працює
Фредерік Базін

91

Я здивований, що ніхто не згадав, що ви можете зробити це за допомогою f-рядків у Python 3.6 так просто, як це:

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

... де частина після двокрапки є специфікатором формату. Кома є символом роздільника, який ви хочете, тому f"{num:_}"використовує підкреслення замість коми.

Це еквівалент використання format(num, ",")для більш старих версій python 3.


39

Ось однорядкова заміна регулярного виразу:

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 цифрами змініть специфікатор формату на %.3f:

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

Примітка: Не працює правильно з більш ніж трьома десятковими цифрами, оскільки буде спроба групувати десяткову частину:

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

1
використовуйте багатослівний режим, і ви можете мати коментарі прямо у коді
Даніель Стракабошко,

Не могли ви замінити "(?! \ D)" на "$"?
GL2014

28

Це те, що я роблю для поплавків. Хоча, чесно кажучи, я не впевнений, для яких версій це працює - я використовую 2.7:

my_number = 4385893.382939491

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

Повернення: 4,385,893,38

Оновлення. Нещодавно у мене виникла проблема з цим форматом (не могла сказати точну причину), але вдалося виправити її, скинувши 0:

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

19

Ви також можете використовувати '{:n}'.format( value )для представлення локалів. Я думаю, що це найпростіший спосіб для локального рішення.

Для отримання додаткової інформації шукайте thousandsв Python DOC .

Для валюти можна використовувати locale.currency, встановивши прапор grouping:

Код

import locale

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

Вихідні дані

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

13

Трохи розширюючи відповідь Яна Шнайдера:

Якщо ви хочете використовувати спеціальний роздільник тисяч, найпростішим рішенням є:

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

Приклади

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

Якщо ви хочете, щоб німецьке представництво було таким, воно стає трохи складніше:

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

Трохи коротше:'{:_.2f}'.format(12345.6789).replace('.', ',').replace('_', '.')
Том Поль

12

Я впевнений, що для цього повинна бути стандартна функція бібліотеки, але було цікаво спробувати записати її самостійно за допомогою рекурсії, ось ось що я придумав:

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)

Сказавши, що якщо хтось інший знайде стандартний спосіб це зробити, вам слід скористатися цим.


На жаль, працює не у всіх випадках. intToStringWithCommas (1000.1) -> '1.0001,000'
Nadia Alramli

Він спеціально сказав цілі числа і що це повинно бути максимально просто, тому я вирішив не обробляти типи даних, окрім цілих чисел. Я також зробив це явним у назві функції _int_ToStringWithCommas. Тепер я також додав підвищення, щоб зробити це більш зрозумілим.
Марк Байєрс

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

Він використовує функцію регулярних виразів: lookahead, тобто (?=\d)для того, щоб лише групи з трьох цифр, які мають цифру "після", отримували кому. Я кажу "після", тому що рядок є зворотним у цьому пункті.

[::-1] просто обертає рядок.



7

Пітон 3

-

Цілі числа (без десятків):

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

-

Поплавці (з десятковою):

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

де число раніше fвказує кількість десяткових знаків.

-

Бонус

Функція швидкого та брудного запуску для індійської системи нумерації лак / крош (12,34,567):

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


5

з Python версії 2.6 ви можете це зробити:

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

Для версій Python <2.6 та лише для вашої інформації, ось два вручну рішення, вони перетворюють плавці на ints, але негативні числа працюють правильно:

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'% число прекрасно перетворює число в рядок, він підтримує негативи і він скидає дроби з поплавків, роблячи їх ints;
  • цей показник фрагментів [:: - 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)

2

Я початківець Python, але досвідчений програміст. У мене є Python 3.5, тому я можу просто використовувати кому, але це все-таки цікава вправа програмування. Розглянемо випадок непідписаного цілого числа. Найбільш читаною програмою Python для додавання тисяч роздільників є:

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)

Можна також використати розуміння списку:

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)

Це коротше, і може бути одним вкладишем, але вам доведеться зайнятися розумовою гімнастикою, щоб зрозуміти, чому це працює. В обох випадках ми отримуємо:

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

Перша версія - це більш розумний вибір, якщо ви хочете, щоб програма була зрозумілою.


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'

1
float2comma(12031023.1323)повертає: '12, 031,023.132,3 '
demux

1

Один вкладиш для Python 2.5+ та Python 3 (лише позитивний int):

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

1

Універсальне рішення

У попередніх голосових відповідях я знайшов деякі проблеми з роздільником точок. Я розробив універсальне рішення, де ви можете використовувати все, що завгодно, як роздільник тисячі, не змінюючи локаль . Я знаю, що це не найелегантніше рішення, але це робить роботу. Сміливо вдосконалюйте його!

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

Це робить гроші разом з комами

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

У мене є версія цього коду python 2 та python 3. Я знаю, що питання було задано для python 2, але зараз (через 8 років, хай) люди, ймовірно, будуть використовувати python 3.

Код Python 3:

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: (Редагувати. Код python 2 не працює. Я думаю, що синтаксис відрізняється).

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

Я використовую python 2.5, тому не маю доступу до вбудованого форматування.

Я переглянув код Django intcomma (intcomma_recurs в коді нижче) і зрозумів, що він неефективний, тому що він є рекурсивним, а також компілювати регулярний вираз під час кожного запуску також не дуже добре. Це не обов'язково "питання", оскільки джанго насправді НЕ ТАК зосереджений на такому рівні низької продуктивності. Також я очікував різниці в продуктивності в 10 разів, але це лише в 3 рази повільніше.

З цікавості я реалізував декілька версій intcomma, щоб побачити, які переваги в роботі є при використанні регексу. Мої дані тесту укладають незначну перевагу для цього завдання, але на диво зовсім не так.

Мені було також приємно побачити, про що я підозрював: використання зворотного підходу xrange є непотрібним у випадку no-регулярного виразів, але це робить код виглядати трохи краще за ціною продуктивності ~ 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

Я думав, що одноразове рішення Даніеля Фортунова буде №1 і переможе всі алгоритми, тому що регулярний вираз настільки вдосконалений / оптимізований і кодується в C, але ні. вона потрапляє приблизно вдвічі більше часу інткомми вище, навіть при попередньому компілюванні регулярного вираження.
parity3


-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

-1

Просто підклас 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

8
Мені подобається ідея підкласу, але чи __repr__()правильний метод переосмислення? Я б запропонував відмінити __str__()і залишити в __repr__()спокої, тому що він int(repr(number(928374)))повинен працювати, але int()буде задихатися комами.
steveha

@steveha має хороший момент, але виправданням повинно було бути те, number(repr(number(928374)))що не працює, ні int(repr(number(928374))). Все ж, щоб цей підхід працював безпосередньо з print, як цього вимагала ОП, __str__()метод повинен бути замінений, а не метод __repr__(). Незалежно від цього, схоже, є помилка в логіці вставки основних ядер.
мартіно


-8

Для поплавків:

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

Для ints:

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

5
Це видаляє коми. У той час як ОП попросив спосіб їх додати . Крім того, щось на кшталт float('1,234.52'.translate(None, ','))може бути більш простим і, можливо, швидшим.
Призупинено до подальшого повідомлення.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.