如何仅将数字的字符串哈希值转换为整数

时间:2012-09-07 12:22:51

标签: ruby string integer type-conversion

我从几个不同的XML数据库转储导入的哈希行看起来像这样(但是使用不同的键):

{"Id"=>"1", "Name"=>"Cat", "Description"=>"Feline", "Count"=>"123"}

我尝试使用#to_i,但它将非数字字符串转换为0

"Feline".to_i
# => 0

但我想要的是"Feline"保持字符串的方式,而上例中的IdCount变为整数1和{{1 }}

是否有一种简单的方法可以将将数字的字符串值转换为整数?

7 个答案:

答案 0 :(得分:9)

一行答案: 使用正则表达式方法

h.merge(h) { |k, v| v.match(/\A[+-]?\d+?(\.\d+)?\Z/) ? v.to_i : v }

使用整数方法

h.merge(h) { |k, v| Integer(v) rescue v }

答案 1 :(得分:7)

使用Kernel#Integer

my_hash = {"Id"=>"1", "Name"=>"Cat", "Description"=>"Feline", "Count"=>"123"}
Hash[ my_hash.map{ |a, b| [ a,
                            begin
                              Integer b
                            rescue ArgumentError
                              b
                            end ] } ]

稍后添加:使用我的y_support gem,您可以使哈希操作更简洁。

require 'y_support/core_ext/hash'
my_hash.with_values { |v| begin
                            Integer b
                          rescue ArgumentError
                            b
                          end }

YSupport可由gem install y_support安装,并提供符合您预期效果的Hash#with_keysHash#with_values!Hash#with_keys!以及Hash#modify期望二进制块返回一对值,修改哈希值。有人建议将来将这些方法直接添加到Ruby核心。

答案 2 :(得分:1)

我想你知道哪些字段应该是整数(你的消费代码可能取决于它),所以我建议你转换特定的字段。

c = Hash[h.map { |k,v| [k, %w(Id Count).include?(k) ? Integer(v) : v ] }]

答案 3 :(得分:1)

我有一个相似问题需要解决,农药分析结果以异质(不良设计!)格式进入系统...负整数作为特殊代码(未检测到,未经测试) ,未量化等...),nil作为未检测到的同义词,为量化的化合物浮动,并为通过/失败 boolean 的字符串浮动...等等,这是十年在生产环境中运行时间过长,从来没有未开发的高度修补的应用程序;)

我从高级摩擦论者那里学到的

两件事

0) DON'T ITERATE-MODIFY AN ENUMERABLE (return a copy)

1) YOUR REGEX WON'T COVER ALL CASES

虽然我不是rescue的忠实拥护者,但我认为这符合保持代码整洁的目的。因此,我一直在使用它来减轻我的输入:

ha = { 
 "p_permethrin" => nil, 
 "p_acequinocyl"=>"0.124", 
 "p_captan"=>"2.12", 
 "p_cypermethrin"=>"-6", 
 "p_cyfluthrin"=>"-6",
 "p_fenhexamid"=>"-1", 
 "p_spinetoram"=>"-6", 
 "p_pentachloronitrobenzene"=>"-6", 
 "p_zpass"=>"true"
}

Hash[ha.map{|k,v| [k, (Float(v) rescue v)]}] # allows nil
Hash[ha.map{|k,v| [k, (Float(v) rescue v.to_s)]}] # nit to empty string

我什至

class Hash
  # return a copy of the hash, where values are evaluated as Integer and Float
  def evaluate_values
    Hash[self.map{|k,v| [k, (Float(v) rescue v)]}]
  end
end

答案 4 :(得分:0)

使用正则表达式和三元运算符,您可以将其合并到逻辑某处:

string =~ /^\d+$/ ? string.to_i : string

答案 5 :(得分:0)

这不仅会处理整数,还会处理所有数字。

my_hash = {"Id"=>"1", "Name"=>"Cat", "Description"=>"Feline", "Count"=>"123"}

result = my_hash.inject({}) { |result,(key,value)|
    if value.match(/^\s*[+-]?((\d+_?)*\d+(\.(\d+_?)*\d+)?|\.(\d+_?)*\d+)(\s*|([eE][+-]?(\d+_?)*\d+)\s*)$/)
            result[key.to_sym] = value.to_i
    else
            result[key.to_sym] = value
    end
    result
}

感谢Determine if a string is a valid float value for regexp

答案 6 :(得分:-1)

为String定义一个新方法: String #to_number

class String
  def to_number
    Integer(self) rescue Float(self) rescue self
  end
end

测试它:

"1".to_number => 1
"Cat".to_number => "Cat"