3

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

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

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

"Feline".to_i
# => 0

但我想要的是一种"Feline"保留字符串的方法,而IdCount上面的例子中,和变成整数1123.

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

4

7 回答 7

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 }
于 2012-09-07T12:38:53.810 回答
7

使用内核#整数

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_supportgem,您可以使哈希操作更加简洁。

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_keys, Hash#with_values!, Hash#with_keys!, 做你期望他们做的事情, 并且Hash#modify期望一个二进制块返回一对值, 修改适当的哈希值。已经有人提议在未来将此类方法直接添加到 Ruby 核心中。

于 2012-09-07T12:26:20.950 回答
1

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

c = Hash[h.map { |k,v| [k, %w(Id Count).include?(k) ? Integer(v) : v ] }]
于 2012-09-07T12:47:53.887 回答
1

我有一个类似的问题要解决,其中农药分析的结果以异构(糟糕的设计!)格式进入系统......负整数作为特殊代码(未检测,未测试,未量化等......),nil如未检测到的同义词,用于量化化合物的浮点数和用于通过/失败布尔值的字符串...保持你的马,这是一个 10 年的生产运行,从未经过绿地开发的高度修补的应用程序;)

我从顶级 rubists 那里学到了两件事:

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
于 2018-07-06T10:32:14.403 回答
0

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

string =~ /^\d+$/ ? string.to_i : string
于 2012-09-07T12:29:46.593 回答
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
}

感谢确定字符串是否是正则表达式的有效浮点值

于 2012-09-07T12:43:06.493 回答
-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"
于 2013-04-18T12:48:48.387 回答