如何将数字1000格式化为“1 000”

时间:2011-06-23 18:35:55

标签: ruby function formatting numbers

我需要一种格式化数字的方法。我在我的数据库表中存储了一些数字,例如12500,并希望以此格式12 500打印它们(因此每3位数字就有一个空格)。是否有一种优雅的方式来做到这一点?

12 个答案:

答案 0 :(得分:36)

请参阅:http://www.justskins.com/forums/format-number-with-comma-37369.html

没有内置的方法(除非你使用Rails,ActiveSupport有方法可以做到这一点)但你可以使用像这样的正则表达式

formatted_n = n.to_s.reverse.gsub(/...(?=.)/,'\&,').reverse

答案 1 :(得分:21)

Activesupport使用此正则表达式(并且没有反向反转)。

10000000.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1 ") #=> "10 000 000"

答案 2 :(得分:9)

如果你正在处理整数,这里的另一种方法相当简洁明了:

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方法中的参数一样简单。

答案 3 :(得分:8)

official document提出了三种不同的方式:

1)使用lookbehind和lookahead(需要oniguruma

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

2)仅使用前瞻。与steenslag的答案完全相同。

3)既不使用前瞻也不使用后瞻

s = 12500.to_s
nil while s.sub!(/(.*\d)(\d{3})/, '\1 \2')
s # => "12 500"

答案 4 :(得分:4)

非常简单:

number_with_delimiter(12500, delimiter: " ")

请参阅:http://apidock.com/rails/ActionView/Helpers/NumberHelper/number_with_delimiter

答案 5 :(得分:3)

所以,这是非常疯狂和hackish,但它完成了工作......

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

答案 6 :(得分:3)

另一种方式:

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"

答案 7 :(得分:2)

其中一个答案都使用n.to_s。 @MrMorphe没有,但他创建了一个阵列join。这是一种既不使用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

答案 8 :(得分:1)

这是旧的,但我能找到的最快,最优雅的方式是:

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

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

我会尝试在某些时候添加基准测试。

答案 9 :(得分:1)

另一种方式: 此处“分隔符为' '(空格),您可以指定','进行货币转换。”

number.to_s.reverse.gsub(%r{([0-9]{3}(?=([0-9])))}, "\\1#{delimiter}").reverse

答案 10 :(得分:0)

我在寻找将值格式化为美元货币的方法时偶然发现了这个问题。我对所提出的正则表达式解决方案略有不同:

amt = 1234567890.12
f_amt = format("$%.2f",amt)
i = f_amt.index(".")
while i > 4
  f_amt[i-3]=","+f_amt[i-3]
  i = f_amt.index(",")
end

f_amt
=> "$1,234,567,890.12"

这可以参数化以格式化其他货币。

答案 11 :(得分:-2)

我知道这是一个老问题,但是。

为什么不使用子字符串替换。

伪代码中的

....

String numberAsString = convertNumberToString(123456);
int numLength = V.length;//determine length of string

String separatedWithSpaces = null;

for(int i=1; i<=numlength; i++){//loop over the number
separatedWithSpaces += numberAsString.getCharacterAtPosition(i);
    if(i.mod(3)){//test to see if i when devided by 3 in an integer modulo,
    separatedWithSpaces += " ";

    }//end if

}//end loop

我知道这不是任何特定的语言,但希望你能得到这个想法。

大卫