有人可以解释一下Hash#dig与Hash#fetch有什么区别

Flo*_*Lei -1 ruby ruby-on-rails ruby-hash

我正在尝试获取哈希值中的嵌套值。我已经尝试过使用Hash#fetchHash#dig但是我不知道如何将它们组合在一起。

我的哈希如下。

response = {
   "results":[
      {
         "type":"product_group",
         "value":{
            "destination":"Rome"
         }
      },
      {
         "type":"product_group",
         "value":{
            "destination":"Paris"
         }
      },
      {
         "type":"product_group",
         "value":{
            "destination":"Madrid"
         }
      }
   ]
}
Run Code Online (Sandbox Code Playgroud)

我尝试了以下

response.dig(:results)[0].dig(:value).dig(:destination) #=> nil
response.dig(:results)[0].dig(:value).fetch('destination') #=> Rome
Run Code Online (Sandbox Code Playgroud)

期望的返回值为"Rome"。第二个表达式有效,但我想知道是否可以简化。

我正在使用Ruby v2.5和Rails v5.2.1.1。

Car*_*and 5

Hash#fetch与此处无关。这是因为fetch相同的哈希#[]时一样,这里fetch只有一个参数。因此,让我们集中精力dig

digRuby v2.3中引入了三种方法:Hash#digArray#digOpenStruct#dig。关于这些方法的一个有趣的事情是它们彼此调用(但是在文档中甚至在示例中都没有解释)。在您的问题中,我们可以写:

response.dig(:results, 0, :value, :destination)
  #=> "Rome" 
Run Code Online (Sandbox Code Playgroud)

response是一个哈希,因此Hash#dig求值response[:results]。如果值为,nil则表达式返回nil。例如,

response.dig(:cat, 0, :value, :destination)
  #=> nil
Run Code Online (Sandbox Code Playgroud)

其实response[:results]是一个数组:

arr = response[:results]
  #=> [{:type=>"product_group", :value=>{:destination=>"Rome"}},
  #    {:type=>"product_group", :value=>{:destination=>"Paris"}},
  #    {:type=>"product_group", :value=>{:destination=>"Madrid"}}]
Run Code Online (Sandbox Code Playgroud)

Hash#dig因此调用Array#digarr,获得的散列

h = arr.dig(0)
  #=> {:type=>"product_group", :value=>{:destination=>"Rome"}} 
Run Code Online (Sandbox Code Playgroud)

Array#dig然后调用Hash#digh

g = h.dig(:value)
  #=> {:destination=>"Rome"}
Run Code Online (Sandbox Code Playgroud)

最后,g作为一个哈希,Hash#dig调用Hash#digg

g.dig(:destination)
  #=> "Rome"
Run Code Online (Sandbox Code Playgroud)