Need help converting Perl to Ruby (detecting integers and decimals in strings)

Discussion in 'Ruby' started by Paul, Mar 15, 2007.

  1. Paul

    Paul Guest

    I am trying to convert a Perl script to Ruby and have been having some
    difficulty along the way (mostly because I don't know Perl).

    I am currently stumped on one particular line in the old Perl script:
    ---
    foreach (@rawfields) {if ($_ > 0){$_ = int($_*100)/100}}
    ---

    Background context: @rawfields is an array that holds the contents of
    an imported line from a text file. Here are some sample lines from
    the input file:
    ---
    "0" "0" "0" "0" "0" "0" "Bar"
    "5.66666" "0" "3.566662" "1.383332" "6" "0" "Foo"
    ---

    My guess is that the Perl line iterates through each of the elements
    in the array and rounds any integers to 2 decimals.

    This raises a few problems for me.

    1) How can I easily tell if the (string) value in each array element
    is an integer or has a decimal value?

    => The desired output for text file line 2 is :
    ---
    "5.67" "0" "3.57" "1.38" "6" "0" "Foo"
    ---


    I tried the following in Ruby:
    ---
    @rawfields.each_index do |x|
    if ( @rawfields[x].to_f > 0 )
    @rawfields[x] = ( (( @rawfields[x].to_f * 100 ).round.to_i ).to_f /
    100 ).to_s
    end
    end
    ---

    But it produces the following output:
    ---
    "5.67" "0" "3.57" "1.38" "6.0" "0" "Foo"
    ---

    ....which is close, but not quite what I want. My output file now has
    values like 1.0, 5.0, 62.0, etc. If it's an integer, I don't want to
    see the decimal.

    Can anyone suggest an improvement to my code or a better translation
    from Perl?

    TIA. Paul.
     
    Paul, Mar 15, 2007
    #1
    1. Advertisements

  2. How about

    irb(main):005:0> fields = %w{5.6666 0 Foo}
    => ["5.6666", "0", "Foo"]
    irb(main):006:0> fields.map {|v| sprintf("%4.2f", Float(v)) rescue v}
    => ["5.67", "0.00", "Foo"]

    This uses the fact that Float() will throw if the string is not a valid
    number. If you really need "0" instead of "0.00" you could apply
    another test. If you need the quotes you could do

    irb(main):008:0> puts fields.map {|v| (sprintf("%4.2f", Float(v)) rescue
    v).inspect}.join(" ")
    "5.67" "0.00" "Foo"

    Kind regards

    robert
     
    Robert Klemme, Mar 15, 2007
    #2
    1. Advertisements

  3. => ["5.66666", "0", "3.566662", "1.383332", "6", "0", "Foo"]
    => ["5.67", "0.00", "3.57", "1.38", "6.00", "0.00", "Foo"]

    Breaking it up,

    Float(string) either converts a string to a float, or raises an
    exception if it cannot be so converted.

    % is the sprintf operator, so "%0.2f" % float rounds the float to two
    decimal places and interpolates it into the string. Note that it does
    round properly, as per the printf spec, rather than truncating.

    finally, expression1 rescue expression2 means return expression1,
    unless it raises an exception in which case return expression2

    martin
     
    Martin DeMello, Mar 15, 2007
    #3
  4. Hi --

    See if this helps:

    @rawfields.map! do |x|
    if x =~ /^\d+\.\d+$/
    "%.2f" % x
    else
    x
    end
    end


    David

    --
    Q. What is THE Ruby book for Rails developers?
    A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
    Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
    A. Ruby Power and Light, LLC (http://www.rubypal.com)
     
    David A. Black, Mar 15, 2007
    #4
  5. oops - missed the fact that you didn't want integers converted into
    decimals. Best way I can think of is a two level try/rescue-try/rescue
    Float(field) rescue field}
    => ["5.67", "0", "3.57", "1.38", "6", "0", "Foo"]

    More explicitly

    rawfields.map do |field|
    begin
    "%d" % Integer(field)
    rescue
    begin
    "%0.2f" % Float(field)
    rescue
    field
    end
    end
    end

    martin
     
    Martin DeMello, Mar 15, 2007
    #5
  6. Paul

    Jon Garvin Guest

    rawfields.map { |f| f.to_f.to_s == f ? "%0.2f" % f.to_f : f }
    => ["5.67", "0", "3.57", "1.38", "6", "0", "Foo"]
     
    Jon Garvin, Mar 15, 2007
    #6
  7. Paul

    Paul Guest

    That is brilliant! Thank you, Jon! Of all the good suggestions
    posted, I like this one best. You guys all rock! Thanks so much for
    the responses.

    Cheers! Paul. =)
     
    Paul, Mar 16, 2007
    #7
  8. rawfields.map{|f| Integer(f) rescue Float(f) rescue f}
     
    Michael Fellinger, Mar 16, 2007
    #8
  9. Hi --

    That doesn't produce the desired output.


    David

    --
    Q. What is THE Ruby book for Rails developers?
    A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
    (See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
    Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
    A. Ruby Power and Light, LLC (http://www.rubypal.com)
     
    David A. Black, Mar 18, 2007
    #9
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.