Find the type of content (number, date, time, string, etc.) inside the string

I am trying to parse a CSV file and automatically create a table for it using SQL commands. The first row in CSV gives the column headers. But I need to specify a column type for each.

Is there any function in Ruby that will find the type of content in each field. For example, the CSV line:

"12012", "Test", "1233.22", "12:21:22", "10/10/2009"

must create type types

['integer', 'string', 'float', 'time', 'date']

Thanks!

+5
source share
3 answers
require 'time'

def to_something(str)
  if (num = Integer(str) rescue Float(str) rescue nil)
    num
  elsif (tm = Time.parse(str)) == Time.now
    # Time.parse does not raise an error for invalid input
    str
  else 
    tm
  end
end

%w{12012 1233.22 12:21:22 10/10/2009 Test}.each do |str|
  something = to_something(str)
  p [str, something, something.class]
end

Results in

["12012", 12012, Fixnum]
["1233.22", 1233.22, Float]
["12:21:22", Sat Sep 12 12:21:22 -0400 2009, Time]
["10/10/2009", Sat Oct 10 00:00:00 -0400 2009, Time]
["Test", "Test", String]

Update for ruby ​​1.9.3: the time class in stdlib now throws an exception if it cannot parse the string, therefore:

def to_something(str)
  duck = (Integer(str) rescue Float(str) rescue Time.parse(str) rescue nil)
  duck.nil? ? str : duck
end
+7
source

This could lead to a launch.

, . , , ...

$ irb
>> t = { "String" => "string", "Fixnum" => "integer", "Float" => "float" }
=> {"Float"=>"float", "Fixnum"=>"integer", "String"=>"string"}
>> ["xyz", 123, 123.455].map { |x| t[x.class.to_s] }
=> ["string", "integer", "float"]

, :

$ irb
>> t = { String => "string", Fixnum => "integer", Float => "float" }
=> {String=>"string", Float=>"float", Fixnum=>"integer"}
>> ["xyz", 123, 123.455].map { |x| t[x.class] }
=> ["string", "integer", "float"]
+1

If you are disassembling CSV, take a look at this great solution from CSV Analysis with Ruby

require 'csv'

CSV::Converters[:blank_to_nil] = lambda do |field|
  field && field.empty? ? nil : field
end

body = "col1,col2\nq,r\n1,2"
csv = CSV.new(body, :headers => true, :header_converters => :symbol, :converters => [:all, :blank_to_nil])
csv_hash = csv.to_a.map {|row| row.to_hash }

csv_hash.each do |row|
  puts row
  puts row.map{ |k,v|  v.class }.join(",")
end

Exit

{:col1=>"q", :col2=>"r"}
String,String
{:col1=>1, :col2=>2}
Fixnum,Fixnum
0
source

All Articles