Как отформатировать число 1000 как «1 000» - PullRequest
29 голосов
/ 23 июня 2011

Мне нужен способ форматирования чисел. Я сохранил некоторые цифры в своей таблице БД, например, 12500, и хотел бы напечатать их в этом формате 12 500 (таким образом, каждые 3 цифры есть пробел). Есть ли элегантный способ сделать это?

Ответы [ 12 ]

36 голосов
/ 23 июня 2011

см .: http://www.justskins.com/forums/format-number-with-comma-37369.html

нет встроенного пути к нему (если вы не используете Rails, ActiveSupport имеет методы для этого), но вы можете использовать Regex, например

formatted_n = n.to_s.reverse.gsub(/...(?=.)/,'\&,').reverse
21 голосов
/ 24 июня 2011

Activesupport использует это регулярное выражение (и нет обратного обратного хода).

10000000.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1 ") #=> "10 000 000"
9 голосов
/ 14 апреля 2014

Вот еще один метод, который достаточно прост и понятен, если вы имеете дело с целыми числами:

number.to_s.reverse.scan(/\d{1,3}/).join(",").reverse

number            #=> 12345678
.to_s             #=> "12345678"
.reverse          #=> "87654321"
.scan(/\d{1,3}/)  #=> ["876","543","21"]
.join(",")        #=> "876,543,21"
.reverse          #=> "12,345,678"

Отлично работает для целых чисел. Конечно, этот конкретный пример будет разделять число запятыми, но переключиться на пробелы или любой другой разделитель так же просто, как заменить параметр в методе join.

8 голосов
/ 24 июня 2011

Официальный документ предлагает три различных способа:

1) Использование lookbehind и lookahead (Требуется oniguruma )

12500.to_s.gsub(/(?<=\d)(?=(?:\d{3})+\z)/, ' ')
# => "12 500"

2)Используя только lookahead.Идентичен ответу Стинслага

4 голосов
/ 22 апреля 2016

очень просто:

number_with_delimiter(12500, delimiter: " ")

см .: http://apidock.com/rails/ActionView/Helpers/NumberHelper/number_with_delimiter

3 голосов
/ 23 июня 2011

Другой способ:

12500.to_s.reverse().split(//).inject() {|x,i| (x.gsub(/ /,"").length % 3 == 0 ) ? x + " " + i : x + i}.reverse()

Вы всегда можете открыть класс Fixnum и добавить его для удобства:

module FormatNums
  def spaceify
    self.to_s.reverse().split(//).inject() {|x,i| (x.gsub(/ /,"").length % 3 == 0 ) ? x + " " + i : x + i}.reverse()
  end
end

class Fixnum
  include FormatNums
end

12500.spaceify # => "12 500"
3 голосов
/ 23 июня 2011

Итак, это довольно сумасшедший и хакерский, но он выполняет свою работу ...

12500.to_s.split("").reverse.each_slice(3).map {|y| y.join("").reverse}.reverse.join(" ")
 => "12 500" 

.to_s: convert to string
.split(""): split into separate digits
.reverse: reverse order
.each_slice(3): peel of each three digits (working from back end due to reverse)
.map {|y| y.join("").reverse}: map into an array for each three digits - join back together with no delimiter and reverse order back to original
.reverse: reverse order of mapped array
.join(" "): join mapped array back together with space delimiter
2 голосов
/ 31 октября 2014

Все ответы, кроме одного, используют n.to_s. @ MrMorphe's нет, но он создает массив, который будет join ed. Вот способ, который не использует ни Fixnum # to_s , ни Array # join .

def separate(n,c=' ')
  m = n
  str = ''
  loop do
    m,r = m.divmod(1000)
    return str.insert(0,"#{r}") if m.zero?
    str.insert(0,"#{c}#{"%03d" % r}")
  end
end

separate(1)       #=>         "1"
separate(12)      #=>        "12"
separate(123)     #=>       "123"
separate(1234)    #=>     "1 234"
separate(12045)   #=>    "12 045"
separate(123456)  #=>   "123 456"
separate(1234000) #=> "1 234 000"

Хм. Эта колонка справа наклонена?

Другой способ, который использует to_s, но не join:

def separate(n, c=' ')
  str = n.to_s
  sz = str.size
  (3...sz).step(3) { |i| str.insert(sz-i, c) }
  str
end
1 голос
/ 01 ноября 2014

Другой способ: Здесь «разделитель - ' ' (пробел), вы можете указать ',' для конвертации денег».

number.to_s.reverse.gsub(%r{([0-9]{3}(?=([0-9])))}, "\\1#{delimiter}").reverse
1 голос
/ 26 июня 2014

Это старый, но самый быстрый и изящный способ, который я смог найти для этого:

def r_delim(s, e)                                                               
  (a = e%1000) > 0 ? r_delim(s, e/1000) : return; s << a                        
end

r_delim([], 1234567).join(',')

В какой-то момент я попытаюсь добавить тесты.

...