首页 > 解决方案 > TypeError 没有将 Symbol 隐式转换为 Integer

问题描述

哈希

data = {
  :recordset => {
    :row => {
      :property => [
        {:name => "Code",     :value => "C0001"}, 
        {:name => "Customer", :value => "ROSSI MARIO"}
      ]
    }
  },
  :@xmlns => "http://localhost/test"
}

使用的代码

result = data[:recordset][:row].each_with_object([]) do |hash, out|
           out << hash[:property].each_with_object({}) do |h, o|
                    o[h[:name]] = h[:value]
                  end
         end

我无法得到以下输出:

[{"Code"=>"C0001", "Customer"=>"ROSSI MARIO", "Phone1"=>"1234567890"}

错误信息:

TypeError 没有将 Symbol 隐式转换为 Integer

在多条记录的情况下它可以正常工作

data = {
  :recordset => {
    :row => [{
      :property => [
        {:name => "Code",     :value => "C0001"},
        {:name => "Customer", :value => "ROSSI MARIO"},
        {:name => "Phone1",   :value => "1234567890"}
      ]
    }, {
      :property => [
        {:name => "Code",     :value => "C0002"},
        {:name => "Customer", :value => "VERDE VINCENT"},
        {:name => "Phone1",   :value => "9876543210"},
        {:name => "Phone2",   :value => "2468101214"}
      ]
    }]
  },
  :@xmlns => "http://localhost/test"
}

使用的代码

data.keys
#=> [:recordset, :@xmlns] 

data[:recordset][:row].count
#=> 2   # There are 2 set of attribute-value pairs


result = data[:recordset][:row].each_with_object([]) do |hash, out|
           out << hash[:property].each_with_object({}) do |h, o|
                    o[h[:name]] = h[:value]
                  end
         end
#=> [
#   {"Code"=>"C0001", "Customer"=>"ROSSI MARIO", "Phone1"=>"1234567890"},
#   {"Code"=>"C0002", "Customer"=>"VERDE VINCENT", "Phone1"=>"9876543210", "Phone2"=>"2468101214"}
# ] 

标签: ruby-on-railsruby

解决方案


在第一种情况下data[:recordset][:row]不是一个数组,它是一个哈希,所以当你迭代它时,hash变量就变成了数组:

[:property, [{:name=>"Code", :value=>"C0001"}, {:name=>"Customer", :value=>"ROSSI MARIO"}]]

在第二种情况下,它是一个数组,而不是一个哈希,所以当你迭代它时,它就变成了哈希:

{:property=>[{:name=>"Code", :value=>"C0001"}, {:name=>"Customer", :value=>"ROSSI MARIO"}, {:name=>"Phone1", :value=>"1234567890"}]}

你总是假设它是第二种格式。您可以将其强制为一个数组,然后将其展平 1 级以将两个实例视为相同:

result = [data[:recordset][:row]].flatten(1).each_with_object([]) do |hash, out|
  out << hash[:property].each_with_object({}) do |h, o|
    o[h[:name]] = h[:value]
  end
end

# => [{"Code"=>"C0001", "Customer"=>"ROSSI MARIO"}] # result from example 1
# => [{"Code"=>"C0001", "Customer"=>"ROSSI MARIO", "Phone1"=>"1234567890"},
#     {"Code"=>"C0002", "Customer"=>"VERDE VINCENT",
#      "Phone1"=>"9876543210", "Phone2"=>"2468101214"}] # result from example 2

尝试使用Kernal#Array()而不是很诱人[].flatten(1),但您必须记住 Hash 实现to_a返回键和值的嵌套数组,因此Kernal#Array()不会像您希望的那样工作:

Array(data[:recordset][:row]) # using the first example data
# => [[:property, [{:name=>"Code", :value=>"C0001"}, {:name=>"Customer", :value=>"ROSSI MARIO"}]]]

推荐阅读