【问题标题】:Ruby -- convert a nested hash to a multidimensional arrayRuby——将嵌套散列转换为多维数组
【发布时间】:2018-02-10 16:25:32
【问题描述】:

我有一个名为h 的哈希。我想将内容存储在一个名为ar 的多维数组中。我收到错误 no implicit conversion from nil to integer

这是我的代码:

h = {"bob" => {email: "abc" , tel: "123"} , "daisy" => {email: "cab" , tel: "123456"}}

keys = h.keys

l = h.length 

ar = Array.new(l) { Array.new(3) }

for i in 0..l-1
  ar[[2][i]] = keys[i]
  ar[[1][i]] = h[keys[i]][:email]
  ar[[0][i]] = h[keys[i]][:tel]
end

puts ar.to_s

想要的输出是:

[[email_1, email_2, ..][tel_1, tel_2, ..][name_1, name_2, ..]]

例如:

[["abc", "cab"] , ["123", "123456"] , ["bob", "daisy"]]

【问题讨论】:

    标签: arrays ruby list dictionary hash


    【解决方案1】:

    我会这样处理:

    h.values.each_with_object({}) do |h,obj|
      obj.merge!(h) { |_k,v1,v2| ([v1] << v2).flatten }
    end.values << h.keys
    #=> [["abc", "cab"], ["123", "123456"], ["bob", "daisy"]]
    
    • 首先获取所有values(作为哈希)
    • 用累加器循环遍历它们 ({})
    • merge! 将值放入累加器并在冲突时将它们附加到 array
    • 从累加器返回values
    • 然后追加原来的keys

    这没有@mudasobwa 的回答那么明确,它依赖于第一个value 的顺序来确定输出。例如如果 :tel 出现在 :email 之前,则前 2 个元素的顺序会颠倒

    【讨论】:

    • 您的代码有效。您能否建议一种改进我的方法或告诉我哪里出错了
    • @AkshatBansal 让我们从您认为ar[[2][0]] 代表的内容开始,因为它实际上意味着ar[2],因为您正在创建一个Array ([2]),然后在其上调用Array#[],因此@ 987654334@ 这里的问题是[2][1] #=&gt; nil 所以ar[[2][1]] 等同于ar[nil],这会在第二次迭代中引发错误。你的意思是ar[2][0]ar[2][1] 但这也有错误ar = [[nil,nil,nil],[nil,nil,nil]] (注意没有ar[2] 只有ar[0]ar[1]
    【解决方案2】:

    [2][i]i &gt; 0 返回nilar[nil] 引发异常。

    这是你要做的:

    arr = h.map { |k, v| [v[:email], v[:tel], k] }.reduce(&:zip)
    

    你的代码工作:

    改变

    ar = Array.new(l) { Array.new(3) }
    

    ar = Array.new(3) { Array.new(l) }
    

    改变

    ar[[2][i]] = keys[i]
    ar[[1][i]] = h[keys[i]][:email]
    ar[[0][i]] = h[keys[i]][:tel]
    

    ar[2][i] = keys[i]
    ar[1][i] = h[keys[i]][:email]
    ar[0][i] = h[keys[i]][:tel]
    

    【讨论】:

    • 对不起,我没有明白你的意思,你能告诉我应该怎么做来纠正它
    • @AkshatBansal 我添加了一些示例
    • 它没有给出错误但也没有给出所需的输出。
    • @AkshatBansal 我看到你已经改变了问题,所以我添加了最后一段
    • @AkshatBansal 你试过最后一个变种了吗?
    【解决方案3】:

    您最应该做的是停止使用 Ruby 语法编写 PHP 代码。这是如何在 Ruby 中完成的:

    h.map { |k, v| [v[:email], v[:tel], k] }.reduce(&:zip)
    

    或者,更好的是,如果您确定嵌套哈希中的元素顺序:

    h.map { |k, v| [*v.values, k] }.reduce(&:zip).map(&:flatten)
    

    mapreducezip 的所有方法都在 the documentation 中进行了详细描述。

    【讨论】:

    • 您的 “甚至更好” 依赖于元素的顺序需要与您的第一个示例(更好)不同的顺序相同
    • @engineersmnky ...评论中准确地描述为“更好”,不是吗?
    • 描述警告并不会使解决方案“更好”,但它是吗?是什么让它变得更好?减少击键次数?
    • @engineersmnky 确实,我总是忘记谁使结果变平,谁没有。之后它适用于任何数量的带有.map(&amp;:flatten) 的键。
    • @engineersmnky 永远欢迎;前一个可能是给定输入的确切解决方案。后者是广义的。 :)
    【解决方案4】:
    h.map { |k, v| [*v.values_at(:email, :tel), k] }.transpose
      #=> [["abc", "cab"], ["123", "123456"], ["bob", "daisy"]]
    

    中间计算如下。

    h.map { |k, v| [*v.values_at(:email, :tel), k] }
      #=> [["abc", "123", "bob"], ["cab", "123456", "daisy"]]
    

    【讨论】:

      猜你喜欢
      • 2022-01-09
      • 2016-09-28
      • 1970-01-01
      • 2010-12-27
      • 2018-10-27
      • 2014-12-30
      • 1970-01-01
      • 2012-03-27
      • 2012-11-24
      相关资源
      最近更新 更多