如何使用挖掘方法几个为儿童对象

时间:2018-06-12 20:53:33

标签: ruby

我有一个哈希

{:result=>
  {:"1"=>
    [{:"1"=>1,
      :"2"=>"4698192612070913717",
      :"5"=>
      {:"1"=>{:"1"=>"1.0.0"},
        :"2"=>
        {:"1"=>1,
          :"2"=>"1525341956127",
          :"3"=>1000000000,
          :"4"=>0,
          :"5"=>{:"1"=>1000000000}},
        :"3"=>["17"],
        :"6"=>"4704522736971289334",
        :"8"=>["4618851880555471022"],
        :"9"=>[1]},
      :"6"=>{:"3"=>{:"2"=>false}, :"4"=>{:"1"=>false}},
      :"7"=>{:"1"=>1},
      :"8"=>"production"},
    {:"1"=>4,
      :"2"=>"4700283765268993541",
      :"6"=>{:"2"=>{:"1"=>200}, :"3"=>{:"2"=>false}, :"4"=>{:"1"=>false}},
      :"8"=>"beta"},
    {:"1"=>5,
      :"2"=>"4699074054925986704",
      :"6"=>{:"2"=>{:"1"=>100}, :"3"=>{:"2"=>false}, :"4"=>{:"1"=>false}},
      :"8"=>"alpha"},
    {:"1"=>10,
      :"2"=>"4697702456121346981",
      :"6"=>{:"2"=>{:"1"=>50}, :"3"=>{:"2"=>false}, :"4"=>{:"1"=>false}},
      :"8"=>"internal"}],
  :"3"=>{:"1"=>true, :"2"=>{:"1"=>{:"1"=>false}, :"2"=>{:"1"=>false}}},
  :"4"=>false},
:xsrf=>"AMtNNDFJl06mR54j2zxFjYIYfGQR22sUKA:1528830206790"}

我正在寻找返回值或nil的简单方法

我试过这个

result[:'result'][:'1'][1].dig(:'5').dig(:'1').dig(:'1')

但它无效

我该怎么做才能避免这个

if result[:'result'][:'1'][1].dig(:'5')
puts result[:'result'][:'1'][1][:'5'][:'1'][:'1']
end

2 个答案:

答案 0 :(得分:1)

挖掘背后的想法是,你可以同时深入到哈希的几个级别,如果在“挖掘”期间任何级别的密钥不存在,则返回nil。因此,result[:'result'][:'1'][1].dig(:'5', :'1', :'1')将执行您正在寻找的内容并清理您的代码。事实上,如果你想做result.dig(:result, :'1', 1, :'5', :'1', :'1')

,你可以让它更安全一些

答案 1 :(得分:1)

dig不是单一方法,而是一系列方法,所有这些方法都在Ruby v2.3中首次亮相:Array#digHash#digStruct#digOpenStruct#dig

例如,

h = { a: [1, { c: 2, d: 3 }], b: 2 }
h.dig(:a, 1, :d)
  #=> 3

使用Hash#dig因为dig的接收器是哈希值。此外,人们可能会期望,在中间计算中,dig已挖掘出[1, { c: 2, d: 3 }],它会将铲子传给Array#dig进行进一步挖掘。

假设

h = { a: [1, 2] }

然后

h.dig(:a, 1)        #=> 2
h.dig(:a).dig(1)    #=> 2

这是否意味着两者是等价的?试试这个:

h.dig('cat', 1)     #=> nil
h.dig('cat').dig(1) #=> NoMethodError: undefined method `dig' for nil:NilClass

异常是由于h.dig('cat') #=> nilNilClass没有实例方法dig,因此nil.dig(1)引发了异常。不,这两个表达方式不相同。

如果变量result的值是OPs哈希,我们(如@Isaiah所指出的)有以下内容。

result.dig(:result, :'1', 0, :"5", :"1", :"1")
  #=> "1.0.0"
result.dig(:result, :'1', 0, :cat, :"1", :"1")
  #=> nil

请注意,如果使用了错误的数据类型,dig仍会引发异常:

[1, 2].dig(:a)
  #=> TypeError: no implicit conversion of Symbol into Integer

为了支持2.3之前的Ruby版本(其中dig不可用),我们可以使用Enumerable#reduce(又名inject)编写以下内容。

arr = [:result, :'1', 0, :"5", :"1", :"1"]
arr.reduce(result) { |memo, obj| memo && memo[obj] }
  #=> "1.0.0"

arr = [:result, :'1', 0, :cat, :"1", :"1"]
arr.reduce(result) { |memo, obj| memo && memo[obj] }
  #=> nil