2012-02-06 9 views
5

मैं किसी संख्या को स्वरूपित करते समय प्रत्येक तीसरे वर्ण पर एक स्थान डालना चाहता हूं। इस कल्पना के अनुसार:प्रत्येक तीसरे अंक पर विभाजित करने के लिए संख्या को स्वरूपित करना

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" 

हो सकता है कि वहाँ एक तर्क यह है कि नियमित अभिव्यक्ति आश्चर्यजनक पढ़ने योग्य नहीं हैं, लेकिन व्यक्तिगत रूप से मुझे लगता है कि वे सरल कर रहे हैं रिकर्सन में सोचने की तुलना में समझने के लिए।

+0

+1 आप सही मेरे मन से बाहर जवाब ले लिया! =) – maerics

+0

अच्छा टुकड़ा। मुझे लगता है कि कई डेवलपर्स रेगेक्स के बारे में नहीं जानते हैं जो मुझे इससे बचाता है - लेकिन यह भी रिकर्सन के बारे में भी सच है! मुद्दा लेना। – froderik

+0

बेशक यहां जादू नियमित अभिव्यक्ति नहीं है - एक बार जब आप विधि के लक्ष्य को जानते हैं तो 'हर 3 वर्णों को रिक्त स्थान जोड़ना' चुनना आसान होता है। 'रिवर्स'/'रिवर्स' एकमात्र वास्तविक मानसिक छलांग है। – Gareth

3

क्या यह रेल है?

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

यह ActionView::Helpers::NumberHelper से आता है।

आपको लगता है कि नकारात्मक संख्या और दशमलव बिंदु के साथ काम करता एक स्टैंडअलोन संस्करण चाहते हैं, इस का उपयोग करें: प्रत्येक अंक कि केवल 3 के समूह द्वारा पीछा किया जाता कैद:

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

regex में तर्क यह है अंक (कोई शेष अंक नहीं), और इसे अंतरिक्ष के साथ आउटपुट करें।

+0

आपकी 123 ~ 12367 "' 123.4567' के लिए विफल रहता है। हालांकि, रेल संस्करण का उल्लेख करने के लिए +1, जहां स्रोत कोड देखा जा सकता है। (एक बार जब आप i18n "fluff" को फेंक देते हैं, तो 'gsub!' का उपयोग करके 'gsub!' का उपयोग करके ''' पर विभाजित करने का मूल फिर से सुरुचिपूर्ण होता है।) – Phrogz

+0

अच्छी पकड़। मैंने सहायक को नकल करने के लिए मेरा अद्यतन किया है। अब उस मामले में काम करना चाहिए। –

5

गैरेथ के समाधान का एक छोटा सा संशोधन (एक अधिक जटिल regexp, लेकिन कोई स्ट्रिंग पीछे):

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

एक्शन व्यू डॉक्स में जिस चीज को आप 'sep' कहते हैं उसे डिलीमीटर कहा जाता है। विभाजक और पूर्णांक अंकों के बीच char के लिए विभाजक का उपयोग किया जाता है। (मुझे सबसे अच्छा क्या है, इस बारे में कोई राय नहीं है, लेकिन मैं पहले उलझन में था।) अन्यथा +1 – steenslag

+0

ओह, मेरी कोशिश को 'न्यूमेरिक' पर परिभाषित 'to_s_with_delim' कहा जाता था, इसलिए मैंने देखा।'spaces_on' IMHO का एक बहुत अच्छा तरीका नाम नहीं है। लेकिन अभी भी +1 :) – steenslag

संबंधित मुद्दे