Diyelim ki 1234567 sayısını 1,234,567 şeklinde yazdırmak istiyoruz. Bunu nasıl başaracağız? Aslında bunun için birden çok yöntemimiz var:
Local modülü ile
import locale
locale.setlocale(locale.LC_ALL, '') # otomatik kullanım için '' olarak bırakın. ya da 'en_US.UTF-8' gibi bir formata zorlayabilirsiniz.
'{:n}'.format(value) # Python ≥2.7
f'{value:n}' # Python ≥3.6
Local modülü olmadan
'{:,}'.format(value) # Python ≥2.7
f'{value:,}' # Python ≥3.6
Yine local modülü kullanmadan deneyebileceğimiz bir yol da aşağıdaki:
def intWithCommas(x):
if type(x) not in [type(0), type(0L)]:
raise TypeError("Parametre tam sayı olmalı")
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)
regex
Tek satırlık bir regex ile de aynı işlemi yapabiliriz:
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)
Yalnızca tamsayı çıktıları için aşağıdaki kullanılabilir:
import re
val = 1234567890
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%d" % val)
# Çıktı: '1,234,567,890'
val = 1234567890.1234567890
# Çıktı: '1,234,567,890'
Veya 4 basamaktan az olan floatlar için biçim belirleyicisini %.3f
şekilde değiştirebiliriz:
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.3f" % val)
# Çıktı: '1,234,567,890.123'
Not: Ondalıklı sayıları da gruplandırmaya çalışacağından üçten fazla basamakta bu çözüm düzgün çalışmayacaktır:
re.sub("(\d)(?=(\d{3})+(?!\d))", r"\1,", "%.5f" % val)
# çıktı: '1,234,567,890.12,346'
Regex nasıl çalışır?
Hadi bu regexi parçalayalım:
re.sub(desen, repl, string)
pattern = \
"(\d) # bir sayı bul...
(?= # arkasından gelen...
(\d{3})+ # bir veya daha fazla üçlü grup içeren...
(?!\d) # ama sonrasında sayı gelmeyen.
)",
repl = \
r"\1,", # bu bir sayıyı kendisi ve sonrasında gelen bir virgül ile değiştir,
# sonra daha fazla eşleşme için aramaya devam et
# (re.sub() tüm eşleşmeleri değiştirir)
string = \
"%d" % val # dizeyi ondalık olarak düzenle