我正在尝试在哈希中获取嵌套值。我已经尝试过使用Hash#fetch
和Hash#dig
,但是我不知道应该如何结合使用它们。
我的哈希如下。
response = {
"results":[
{
"type":"product_group",
"value":{
"destination":"Rome"
}
},
{
"type":"product_group",
"value":{
"destination":"Paris"
}
},
{
"type":"product_group",
"value":{
"destination":"Madrid"
}
}
]
}
我尝试了以下
response.dig(:results)[0].dig(:value).dig(:destination) #=> nil
response.dig(:results)[0].dig(:value).fetch('destination') #=> Rome
期望的返回值为"Rome"
。第二个表达式有效,但是我想知道它是否可以简化。
我正在使用Ruby v2.5和Rails v5.2.1.1。
答案 0 :(得分:3)
Hash#fetch与此处无关。这是因为当fetch
仅具有单个参数时,fetch
与Hash#[]相同。因此,让我们专注于dig
。
在Ruby v2.3中引入了三个dig
方法家族:Hash#dig,Array#dig和OpenStruct#dig。关于这些方法的一个有趣的事情是它们彼此调用(但是在文档中甚至在示例中都没有解释)。在您遇到的问题中,我们可以这样写:
response.dig(:results, 0, :value, :destination)
#=> "Rome"
response
是一个哈希,因此Hash#dig
评估response[:results]
。如果其值为nil
,则表达式返回nil
。例如,
response.dig(:cat, 0, :value, :destination)
#=> nil
实际上,response[:results]
是一个数组:
arr = response[:results]
#=> [{:type=>"product_group", :value=>{:destination=>"Rome"}},
# {:type=>"product_group", :value=>{:destination=>"Paris"}},
# {:type=>"product_group", :value=>{:destination=>"Madrid"}}]
Hash#dig
因此在Array#dig
上调用arr
,获得哈希值
h = arr.dig(0)
#=> {:type=>"product_group", :value=>{:destination=>"Rome"}}
Array#dig
然后在Hash#dig
上调用h
:
g = h.dig(:value)
#=> {:destination=>"Rome"}
很老套,g
是一个哈希,Hash#dig
在Hash#dig
上调用g
:
g.dig(:destination)
#=> "Rome"
答案 1 :(得分:1)
dig(key, ...) → object
通过在每个步骤调用
dig
来提取由键对象序列指定的嵌套值,如果中间步骤为nil
,则返回nil
。
fetch(key [, default] ) → obj
fetch(key) {| key | block } → obj
从散列返回给定键的值。如果找不到密钥,则有几种选择:没有其他参数,它将引发
KeyError
异常;如果给出了 default ,则将返回该值;如果指定了可选代码块,则将运行该代码块并返回其结果。
您的示例与众不同:
response = {
"results": [
{
"type": 'product_group',
"value": {
"destination": 'Rome'
}
},
{
"type": 'product_group',
"value": {
"destination": 'Paris'
}
},
{
"type": 'product_group',
"value": {
"destination": 'Madrid'
}
}
]
}
response[:results].first.dig(:value, :destination) #=> "Rome"
response[:results].first.fetch(:value).fetch(:destination) #=> "Rome"