我有一个哈希
{: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
答案 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#dig,Hash#dig,Struct#dig和OpenStruct#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') #=> nil
和NilClass没有实例方法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