Как напечатать число с запятыми в качестве разделителей тысяч?


754

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

Он не должен зависеть от локали, чтобы выбирать между точками и запятыми. Я бы предпочел что-то настолько простое, насколько это возможно.

Ответы:


1739

Локаль не знает

'{:,}'.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'вместо этого целочисленный тип представления.


25
Обратите внимание, что это не будет правильным за пределами США и нескольких других мест, в этом случае выбранный locale.format () является правильным ответом.
Гринго Суаве

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

11
Большое спасибо. Для денежных сумм с двумя десятичными знаками - "{:,. 2f}". Формат (значение)
dlink

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" - обычный форматер в стиле%. У вас может быть только один форматер, но он может быть любым с точки зрения ширины поля и настроек точности.

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: должна быть книга: «Доктор ПЕП: Или Как я научился перестать беспокоиться и любить docs.python.org. " Я перестал запоминать все библиотеки обратно в Python 1.5.6. Что касается locale, я использую как можно меньше.
Майк ДеСимоне

10
Вы можете использовать '' для setlocaleиспользования значения по умолчанию, которое, мы надеемся, будет уместным.
Марк Рэнсом

24
Попробуйте это: locale.setlocale (locale.LC_ALL, '') У меня это сработало
Надя Алрамли

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

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" =)
holms

5
Периоды? Это даже невозможно, Холмс. Этот кусок барахла полностью игнорирует локаль. Интересно, как вы получили этот результат. Ваш пример производит для меня «17 371 830», как и ожидалось.
Кейси Киркхэм

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 не работает
Фредерик Базин

93

Я удивлен, что никто не упомянул, что вы можете сделать это с помощью f-строк в Python 3.6 так просто:

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

... где часть после двоеточия является спецификатором формата. Запятая - это требуемый символ-разделитель, поэтому f"{num:_}"вместо запятой используются подчеркивания.

Это эквивалентно использованию format(num, ",")для более старых версий Python 3.


Это проще, чем любой из ответов с более высоким рейтингом, и не требует дополнительного импорта.
Z4-уровень

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'

NB: некорректно работает с более чем тремя десятичными цифрами, так как он пытается сгруппировать десятичную часть:

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'

14

Немного расширив ответ Яна Шнайдера:

Если вы хотите использовать пользовательский разделитель тысяч, самое простое решение:

'{:,}'.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'
Надя Алрамли

Он специально сказал целые числа, и это должно быть как можно более простым, поэтому я решил не обрабатывать типы данных, кроме целых чисел. Я также сделал это явным образом в имени функции _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] просто переворачивает строку


8

Принятый ответ - хорошо, но я на самом деле предпочитаю format(number,','). Мне легче интерпретировать и запомнить.

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


Работает отлично, также избегая отображения слишком большого количества десятичных цифр для чисел с плавающей запятой.
Rexcirus

7

Python 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 и просто для вашей информации, вот 2 ручных решения, они превращают числа с плавающей точкой в ​​целые, но отрицательные числа работают правильно:

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)

Несколько вещей, чтобы заметить здесь:

  • эта строка: строка = '% d'% число прекрасно преобразует число в строку, поддерживает негативы и отбрасывает дроби из чисел с плавающей точкой, делая их целыми;
  • этот фрагмент indexes [:: - 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, поэтому у меня нет доступа к встроенному форматированию.

Я посмотрел на intcomma кода Django (intcomma_recurs в приведенном ниже коде) и понял, что он неэффективен, потому что он рекурсивный, а также компиляция регулярного выражения при каждом запуске также не очень хорошая вещь. Это не является обязательным «вопросом», поскольку django на самом деле НЕ ТОЧНО сосредоточен на такого рода низкоуровневой производительности. Кроме того, я ожидал разницы в производительности в 10 раз, но она только в 3 раза медленнее.

Из любопытства я реализовал несколько версий intcomma, чтобы увидеть преимущества производительности при использовании регулярных выражений. Мои данные испытаний показывают небольшое преимущество для этой задачи, но на удивление совсем немного.

Мне также было приятно увидеть то, что я подозревал: использование подхода обратного пересчета не требуется в случае без регулярных выражений, но он действительно немного улучшает внешний вид кода за счет производительности ~ 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, но нет .. Я думаю, что шаблон и прогноз слишком дорогие. оно примерно вдвое превышает указанное выше значение intcomma, даже с предварительной компиляцией регулярного выражения.
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менее , чтобы заставить этот подход работать напрямую , как и требовал OP, __str__()метод должен быть переопределен, а не __repr__(). В любом случае, в логике вставки запятой ядра есть ошибка.
Мартино


-8

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

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

Для целых:

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.