Форматирование числа для разделения на каждую третью цифру - PullRequest
5 голосов
/ 07 февраля 2012

Я хочу ставить пробел при каждом третьем символе при форматировании числа. Согласно этой спецификации:

  it "should format an amount" do
    spaces_on( 1202003 ).should == "1 202 003"
  end

и я придумал этот кусок кода, который делает работу

  def spaces_on amount
    thousands = amount / 1000
    remainder = amount % 1000
    if thousands == 0
      "#{remainder}"
    else
      zero_padded_remainder = '%03.f' % remainder
      "#{spaces_on thousands} #{zero_padded_remainder}"
    end
  end

Так что мой вопрос, был ли это лучший способ сделать это. Я подозреваю, что это может быть регулярное выражение, но я не уверен, что мне понравится удобочитаемость этого. (С другой стороны - магия% 03.f тоже не очень читаема ...)

Ответы [ 4 ]

5 голосов
/ 07 февраля 2012

def spaces_on(number,sep=" ")
  number.to_s.tap do |s|
    :go while s.gsub!(/^([^.]*)(\d)(?=(\d{3})+)/, "\\1\\2#{sep}")
  end
end

NUMBERS = [ 1, 12, 123, 1234, 12345, 123456, 1234567,
            1.0, 1.2, 1.23, 1.234, 1.2345, 1.23456, 1.234567,
            12.3, 12.34, 12.345, 12.3456,
            123.4, 123.45, 123.456, 123.4567,
            1234.5, 1234.5, 1234.56, 1234.567,  1234.5678 ]

NUMBERS.each do |n|
  puts "%10s: %s" % [  n, spaces_on(n).inspect ]
  puts "%10s: %s" % [ -n, spaces_on(-n).inspect ]
end

Производит:

         1: "1"
        -1: "-1"
        12: "12"
       -12: "-12"
       123: "123"
      -123: "-123"
      1234: "1 234"
     -1234: "-1 234"
     12345: "12 345"
    -12345: "-12 345"
    123456: "123 456"
   -123456: "-123 456"
   1234567: "1 234 567"
  -1234567: "-1 234 567"
       1.0: "1.0"
      -1.0: "-1.0"
       1.2: "1.2"
      -1.2: "-1.2"
      1.23: "1.23"
     -1.23: "-1.23"
     1.234: "1.234"
    -1.234: "-1.234"
    1.2345: "1.2345"
   -1.2345: "-1.2345"
   1.23456: "1.23456"
  -1.23456: "-1.23456"
  1.234567: "1.234567"
 -1.234567: "-1.234567"
      12.3: "12.3"
     -12.3: "-12.3"
     12.34: "12.34"
    -12.34: "-12.34"
    12.345: "12.345"
   -12.345: "-12.345"
   12.3456: "12.3456"
  -12.3456: "-12.3456"
     123.4: "123.4"
    -123.4: "-123.4"
    123.45: "123.45"
   -123.45: "-123.45"
   123.456: "123.456"
  -123.456: "-123.456"
  123.4567: "123.4567"
 -123.4567: "-123.4567"
    1234.5: "1 234.5"
   -1234.5: "-1 234.5"
    1234.5: "1 234.5"
   -1234.5: "-1 234.5"
   1234.56: "1 234.56"
  -1234.56: "-1 234.56"
  1234.567: "1 234.567"
 -1234.567: "-1 234.567"
 1234.5678: "1 234.5678"
-1234.5678: "-1 234.5678"
5 голосов
/ 07 февраля 2012

Небольшая модификация решения Гарета (более сложное регулярное выражение, но без перестановки строк):

def spaces_on number
  number.to_s.gsub(/\d(?=(...)+$)/, '\0 ')
end

Это работает и для отрицательных чисел (но не работает для чисел с плавающей запятой).

5 голосов
/ 07 февраля 2012
>> def spaces_on number
>>   number.to_s.gsub(/\D/, '').reverse.gsub(/.{3}/, '\0 ').reverse
>> end
=> nil
>> spaces_on 12345678
=> "12 345 678"

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

3 голосов
/ 07 февраля 2012

Это Rails?

number_with_delimiter(@number, :delimiter => ' ')

Это взято из ActionView :: Helpers :: NumberHelper .

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

def spaces_on number
  parts = number.to_s.split('.')
  parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1 ")
  parts.join(".")
end

Логика в регулярном выражении такова: захват каждой цифрыза ним следуют только группы из 3 цифр (без оставшихся цифр) и выведите его с пробелом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...