2012-02-06 9 views
5

で分割する数の書式を設定します。この仕様によると:は、私は数をフォーマットするとき、すべての3番目の文字でスペースに置きたいすべての3桁目

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マジックはどちらか非常に読みやすいではありません....)

答えて

5
>> def spaces_on number 
>> number.to_s.gsub(/\D/, '').reverse.gsub(/.{3}/, '\0 ').reverse 
>> end 
=> nil 
>> spaces_on 12345678 
=> "12 345 678" 

はたぶん正規表現は驚くほど読めないという議論がありますが、個人的に私は、彼らが単純だと思います再帰で考えなければならないことを理解する。このRailsは

+0

1あなたは右の私の心の外に答えを取りました! =) – maerics

+0

素敵な作品。私は、多くの開発者が正規表現について知っているわけではないので、それを避けていることがわかりましたが、再帰についても同様です。撮影ポイント。もちろん – froderik

+0

は、ここでは魔法は、正規表現ではありません - あなたは法の目的を知っていればそれはスペースを追加するごとに3つの文字のビットを選び出すのは簡単です。逆の/逆の唯一の本当の精神的な飛躍です。 – Gareth

3

ですか?

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のグループに続いて各桁をキャプチャ桁数(桁数は残っていない)を入力し、スペースで出力します。

+0

ユアーズ '「123.4 567」'生産、 '123.4567'で失敗しました。しかし、ソースコードを見ることができるRailsのバージョンに言及すると+1します。 – Phrogz

+0

良いキャッチ(あなたが国際化「綿毛」、 '.'、整数半分に'!GSUB '使用し、'再びjoin'ingは一種のエレガントである。上の分割のコアを捨てたら)。私はヘルパーを模倣するために鉱山を更新しました。その場合は今すぐ動作するはずです。 –

5

ガレスのソリューションの小さな変更(より複雑な正規表現、ない文字列反転):

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

それはあまりにも負の数のために動作します(ただし、浮動小数点数には使用できません)。

5

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" 
+0

yay - 深い正規表現のスペースに入る! – froderik

+0

ActionViewドキュメントでは、「sep」と呼ばれるものを区切り文字と呼びます。 separatorは、小数点と整数の間のcharに使用されます。 (私は何が最善であるかについて意見を持っていませんが、最初は混乱していました)。そうでなければ+1 – steenslag

+0

ああ、私の試行は 'Num_'で定義された' to_s_with_delim'と呼ばれました。'spaces_on'は非常に良いメソッド名IMHOではありません。しかし、まだ+1: – steenslag

関連する問題