在字符串中查找内容的类型(数字,日期,时间,字符串等)

时间:2009-09-12 18:46:33

标签: ruby string parsing types

我正在尝试解析CSV文件并使用SQL命令自动为其创建表。 CSV中的第一行显示列标题。但我需要推断每一个的列类型。

Ruby中是否有任何函数可以在每个字段中找到内容的类型。 例如,CSV行:

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

应该产生类似

的类型
['integer', 'string', 'float', 'time', 'date']

谢谢!

3 个答案:

答案 0 :(得分:8)

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

结果

["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]

ruby​​ 1.9.3的更新:如果stdlib中的Time类无法解析字符串,那么它现在会抛出异常,因此:

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

答案 1 :(得分:1)

这可能会让你开始

我没有完整的解决方案,但这可能有助于您入门。您可以自动从示例记录到Class对象数组到字符串表示形式,至少对于某些类型,然后翻译字符串......

$ 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"]

答案 2 :(得分:0)

如果您正在解析CSV,请查看来自Parsing CSV 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

<强>输出

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