On 04.12.2010 23:14, Matt Slay wrote:
>> Pick Axe page 70-75:
>>
>> ruby-1.9.2-head>  s = '12.7 AB36'
>>   =>  "12.7 AB36"
>> ruby-1.9.2-head>  pattern = /\A([0-9.]+)\s*([a-zA-Z]{1,2}[0-9]+)\Z/
>>   =>  /\A([0-9.]+)\s*([a-zA-Z]{1,2}[0-9]+)\Z/
>> ruby-1.9.2-head>  s.match pattern
>>   =>  #<MatchData "12.7 AB36" 1:"12.7" 2:"AB36">
>> ruby-1.9.2-head>  $1
>>   =>  "12.7"
>> ruby-1.9.2-head>  $2
>>   =>  "AB36"

> Peter!!!! You are *THE* man!!!  I actually just bought the 1.9.2 version
> of the book for just $10. Regular Expressions are now on page 97
> (Chapter 7). I'm an FoxPro programmer and just beginning my work in
> Ruby.
>
> I threw your pattern and match command into a Controller action in my
> Rails app, and guess what.... It works!!
>
> Here's my code, after just 1 minute of work, thanks to you. (Some
> refinements are now needed for stupid user input, but I'll get.
>
> I'm so excited to see this come to life so easily. The Ruby community is
> awesome.
>
>    def create
>      @conversion = Conversion.new(params[:conversion])
>      pattern = /\A([0-9.]+)\s*([a-zA-Z]{1,2}[0-9]+)\Z/
>      user_input = @conversion.shaft_size
>      @size = user_input.match pattern
>
>      respond_to do |format|
>        format.html { render :show }
>      end
>    end
>
>
> Now I can access the @size[1] and @size[2] to get what I need done.
>
> How many times can I say "Thanks"???

There are a few things to say about this solution though:

The float part does not exactly match floating point numbers but it 
would also match these sequences: 127.0.0.1, 1..10, 4...3 etc.

"[0-9]" can be replaced by "\d".

Assigning the pattern to a variable and then using that for matching is 
generally less efficient than directly using the pattern.

The pattern "\Z" allows for a newline at the end of the string.  This 
may be OK or not (you can also use #chomp on the input to remove 
trailing line terminators before handing the input to the method).


I would rather go with a combination of Peter's and Josh's solution:

def parse(str)
   if /\A(\d+(?:\.\d+)?)\s*([a-z]{1,2}\d+)\z/i =~ str
     return Float($1), $2
   else
     raise "Invalid input: %p" % str
   end
end

If you need to cope with negative floats and signs in general you can 
change the initial part to

\A([-+]?\d+(?:\.\d+)?)


Few notes and explanations:

The code does the conversion inside the method which may be desirable or 
not - depending on your context.

I picked Float() for added robustness, it will raise an exception if the 
matching was flawed (which should not be the case here).

I added error checking with exception.


Btw, your original description of the sequence is pretty good for direct 
translation into a regular expression.

Kind regards

	robert


-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/