在Ruby中将数字字符串转换为数字

时间:2013-11-21 08:51:39

标签: ruby

我想要一个类似to_numeric(str)的方法,它将数字字符串'str'转换为数字形式,否则返回nil。通过数字形式,如果string是整数方法,则应该返回整数,并且字符串在float中,它应该返回float。

我尝试使用以下代码。它工作正常但如果可能需要更好的解决方案。

def to_numeric(str)
  Integer(str)
rescue
  Float(str) if Float(str) rescue nil
end

我忘记提到的一件重要事情是“我不知道我输入的类型”。

我的用例:

arr = [1, 1.5, 2, 2.5, 4]
some_input = get_input_from_some_source

if arr.include?(to_numeric(some_input))
  # do something
end

5 个答案:

答案 0 :(得分:11)

您可以使用BigDecimal#frac来实现您的目标

require 'bigdecimal'

def to_numeric(anything)
  num = BigDecimal.new(anything.to_s)
  if num.frac == 0
    num.to_i
  else
    num.to_f
  end
end

它可以处理

#floats
to_numeric(2.3) #=> 2.3

#rationals
to_numeric(0.2E-4) #=> 2.0e-05

#integers
to_numeric(1) #=> 1

#big decimals
to_numeric(BigDecimal.new("2"))

并且以字符串的形式浮动,有理数和整数

答案 1 :(得分:4)

使用String#to_f方法将其转换为Float。由于使用duck typing的ruby,您可能不在乎它是Integer

如果它看起来像数字,像数字一样游动,像数字一样呱呱叫,那么它可能是数字。

但请注意! to_f不会抛出任何例外:

"foobar".to_f # => 0 

答案 2 :(得分:2)

如果你真的坚持区分Integer和Floats,那么你可以像这样实现to_numeric

def to_numeric(thing)
  return thing.to_s.to_i if thing.to_s == thing.to_s.to_i.to_s  
  return thing.to_s.to_f if thing.to_s == thing.to_s.to_f.to_s  
  thing
end

它将一个对象转换为整数,如果它的字符串表示看起来像一个整数(与float相同),或者如果不是则返回未改变的东西:

['1', '1.5', 'foo', :bar, '2', '2.5', File].map {|obj| to_numeric obj}
# => [1, 1.5, "foo", :bar, 2, 2.5, File]

答案 3 :(得分:2)

以下是一些选项:

  1. 使用浮动进行比较:

    arr = [1, 1.5, 2, 2.5, 4]
    arr.include? "4.0".to_f #=> true
    
  2. 使用字符串进行比较:

    arr = %w(1 1.5 2 2.5 4)
    arr.include? "4" #=> true
    
  3. 使用eval进行转换:

    eval("4.0") #=> 4.0
    eval("4")   #=> 4
    

    但是在使用eval时你必须​​非常小心,请参阅@ tessi的评论。

答案 4 :(得分:0)

def to_numeric(str)
  str.include?(".") ? str.to_f : str.to_i
end