Forum: Ruby Convert String to Float if and only if the content of the string are digits

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Daniel F. (Guest)
on 2009-01-17 01:05
(Received via mailing list)
Hi All,

Long time reader -- first time poster.  Basically, I have a bunch of
data that is sucked in from a file.  From reading the pick axe book,
it is my understanding that this data by default will be a string even
if the contents of that string are a bunch of digits.  Well, in the
case that a string is solely composed of digits, I want to convert
them to a float for the purpose of using the <=> operator.  I'll just
go ahead and throw in my method and let you guys tear it a part.  The
goal of the function is to soft my array of arrays based on a
particular element defined by a 'key'.  Maybe there is an easier way
to do this all together.

  def sort(*keys) options = {}
    regex = "^(\d)*$"
    newData = Array.new
    keys.reverse!
    keys.each do |key|
      newData = @data
      keyIndex = @header.index(key)
      newData.sort! do |entry1, entry2|
        if (!(entry1[keyIndex].match(regex).nil? && entry2
[keyIndex].match(regex).nil?))
          print "I found only digits\n"
          entry1[keyIndex].to_f <=> entry2[keyIndex].to_f
        else
          #print "I found something other than digits\n"
          entry1[keyIndex] <=> entry2[keyIndex]
        end
      end
    end
    newTable = Table.new({
                           :header => @header,
                           :data => newData
                         })
    newTable
  end

Thanks in advance for you feedback.  Feel free to be brutal -- I have
thick skin and am still learning.
Daniel F. (Guest)
on 2009-01-17 01:31
(Received via mailing list)
On Jan 16, 3:03 pm, Daniel F. <removed_email_address@domain.invalid> wrote:
> particular element defined by a 'key'.  Maybe there is an easier way
>         if (!(entry1[keyIndex].match(regex).nil? && entry2
>                            :header => @header,
>                            :data => newData
>                          })
>     newTable
>   end
>
> Thanks in advance for you feedback.  Feel free to be brutal -- I have
> thick skin and am still learning.

Hi All,

I went ahead and changed my method to:

  def sort(*keys) options = {}
    regex = Regexp.new('^\d+$')
    newData = Array.new
    keys.reverse!
    keys.each do |key|
      newData = @data
      keyIndex = @header.index(key)
      newData.sort! do |entry1, entry2|
        if (entry1[keyIndex] =~ regex && entry2[keyIndex] =~ regex)
          #print "I found only digits\n"
          entry1[keyIndex].to_f <=> entry2[keyIndex].to_f
        else
          #print "I found something other than digits\n"
          entry1[keyIndex] <=> entry2[keyIndex]
        end
      end
    end
    newTable = Table.new({
                           :header => @header,
                           :data => newData
                         })
    newTable
  end

Now the question still remains if there is a better way to do this
sorting.
Jesús Gabriel y Galán (Guest)
on 2009-01-17 17:35
(Received via mailing list)
On Sat, Jan 17, 2009 at 12:28 AM, Daniel F. 
<removed_email_address@domain.invalid>
wrote:
> On Jan 16, 3:03 pm, Daniel F. <removed_email_address@domain.invalid> wrote:

First of all I would like to ask you some questions about the design
of classes and objects you have.
It seems that this is an instance method of a class, cause you are
using a couple of instance variables
(@data and @header). In this method, though, you are modifying @data,
cause you are doing a sort! on it.
Don't know if this side effect is on purpose or not, and if it has
some benefits or problems. It's also not clear to me why you sort the
data in a loop, each time with a different key. Maybe what you want is
to sort based on a set of keys. Your algorithm (sorting by the last
key, then sorting the result by the second to last, etc) might not
yield the same results as sorting based on all keys at the same time.
Maybe you want this (untested):

def sort(*keys, options = {})
# BTW, what is options? You never use it in your code, and the fact
that is outside of the parenthesis, but in the same line makes me
# wonder if you wanted that or what I just wrote
  indexes = keys.map {|k| @head.index(k)}
  sorted = @data.sort do |entry1, entry2|
    first, second = process_values(entry1.values_at(indexes),
entry2.values_at(indexes))
    first <=> second
  end
  Table.new({:header => @header, :data => sorted})
end

# Convert matching pairs of each array with to_f if both contain only
digits
def process_values(first, second)
  regex = /\A(\d*)\z/
  first.zip(second).inject([[],[]]) do |(f,s), (v1,v2)|
    if (v1 =~ regex && v2 =~ regex)
      puts "Only digits found"
      v1 = v1.to_f
      v2 = v2.to_f
    end
    [f << v1, s << v2]
  end
end

This version is sorting based on an array that contains the value for
each key.
Hope this helps,

Jesus.
This topic is locked and can not be replied to.