我想将Ruby字符串解析为它表示的数据类型,就像Google表格执行此操作一样。
例如,当您在Google表格中键入“ hello”时,它将被解释为字符串。 “ 100”作为数字,“ $ 100”作为货币,等等。
更多示例:
字符串“ 2001年1月1日”应转换为日期。
字符串“ true”应转换为布尔值。
无需手动编写正则表达式驱动的case语句来完成此操作的最佳方法是什么?
答案 0 :(得分:3)
必须指定可能的日期格式。如果使用Date#parse,则字符串"Theresa May has announced she will resign"
将返回#<Date: 2019-05-01 ((2458605j,0s,0n),+0s,2299161j)>
。
这是一个开始。
require 'date'
require 'bigdecimal'
def my_class(str)
return true if str == 'true'
return false if str == 'false'
return nil if str == 'nil'
date = DateTime.strptime(str, '%b %d, %Y') rescue nil
return date unless date.nil?
return BigDecimal(str) if str.match?(/\A-?0.\d+e\d+\z/i)
n = Float(str) rescue nil
return n if n && str.include?('.')
n = Integer(str) rescue nil
return n unless n.nil?
raise ArgumentError
end
my_class 'true' #=> true
my_class 'false' #=> true
my_class 'nil' #=> nil
my_class '-32' #=> -32
my_class '0' #=> 0
my_class '1.0' #=> 1.0
my_class '-1.03' #=> -1.03
my_class '1.02e-2' #=> 0.0102
my_class '-1.99E2' #=> -199.0
my_class '-0.99e1' #=> -0.99e1 (BigDecimal)
my_class '-0.99E1' #=> -0.99e1 (BigDecimal)
my_class '0.0' #=> 0.0
my_class 'Jan 1, 2001'
#=> #<DateTime: 2001-01-01T00:00:00+00:00 ((2451911j,0s,0n),+0s,2299161j)>
my_class 'January 1, 2001'
#=> #<DateTime: 2001-01-01T00:00:00+00:00 ((2451911j,0s,0n),+0s,2299161j)>
my_class 'January 32, 2001'
#=> nil
除str = "0.0"
之外,将字符串的返回值转换为BigDecimal
,然后再将其转换回与模式匹配的字符串
r = /\A-?0\.\d+e\d+\z/
(例如BigDecimal("123.4").to_s #=> "0.1234e3"
)。相比之下,用科学计数法表示浮点数的字符串通常会匹配模式
/\A-?[1-9]\.\d+e\d+\z/
因此,我假设只有当字符串与BigDecimal
匹配时,字符串才与r
匹配(尽管我使r
的大小写无关,例如,{{1 }}将被视为"0.12E2"
。