【问题标题】:TypeError no implicit conversion of Symbol into IntegerTypeError 没有将 Symbol 隐式转换为 Integer
【发布时间】:2018-08-27 17:47:35
【问题描述】:

哈希

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-rails ruby


【解决方案1】:

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

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

第二种情况,它是一个Array,不是Hash,所以当你迭代它的时候,它就变成了hash:

{: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"}]]]

【讨论】:

  • 你也可以使用Array(data[:recordset][:row]) 而不是Array(data[:recordset][:row]),我自己觉得它更干净。 Array(1) #=&gt; [1]Array([1]) #=&gt; [1]
  • 啊,很容易忘记。不错的收获。
  • @JohanWentholt 也许我应该留下我原来的评论 :) 因为我说了同样的话并且必须得到纠正,以及我忘记了to_aryto_a 的进展,然后是数组包装:)
【解决方案2】:

如果不是数组,您可以创建一个数组,以便在处理输入之前对其进行规范化。

info = data[:recordset][:row]
info = [info] unless info.is_an? Array
result = info.each_with_object([]) do ....

【讨论】:

    猜你喜欢
    • 2014-03-12
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多