我正在尝试解析CSV文件并使用SQL命令自动为其创建表。 CSV中的第一行显示列标题。但我需要推断每一个的列类型。
Ruby中是否有任何函数可以在每个字段中找到内容的类型。 例如,CSV行:
"12012", "Test", "1233.22", "12:21:22", "10/10/2009"
应该产生类似
的类型['integer', 'string', 'float', 'time', 'date']
谢谢!
答案 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