有人可以解释一下 Hash#dig 和 Hash#fetch 之间的区别吗
Could someone explain me what is the difference between Hash#dig vs Hash#fetch
我正在尝试获取散列中的嵌套值。我试过使用 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
所需的 return 值为 "Rome"
。第二个表达式有效,但我想知道是否可以简化它。
我正在使用 Ruby v2.5 和 Rails v5.2.1.1。
dig(key, ...) → object
Extracts the nested value specified by the sequence of key objects by calling dig
at each step, returning nil
if any intermediate step is nil
.
fetch(key [, default] ) → obj
fetch(key) {| key | block } → obj
Returns a value from the hash for the given key. If the key can't be found, there are several options: With no other arguments, it will raise a KeyError
exception; if default is given, then that will be returned; if the optional code block is specified, then that will be run and its result returned.
看你的例子有什么不同:
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"
Hash#fetch is not relevant here. That's because fetch
is the same as Hash#[] 就像这里一样,fetch
只有一个参数。所以让我们专注于 dig
.
Ruby v2.3 中引入了三个 dig
方法家族:Hash#dig, Array#dig and OpenStruct#dig。这些方法的一个有趣之处在于它们会相互调用(但这在文档中没有解释,甚至在示例中也没有)。在你的问题中我们可以这样写:
response.dig(:results, 0, :value, :destination)
#=> "Rome"
response
是一个散列,因此 Hash#dig
计算 response[:results]
。如果它的值是 nil
那么表达式 returns 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
因此在 arr
上调用 Array#dig
,获取哈希
h = arr.dig(0)
#=> {:type=>"product_group", :value=>{:destination=>"Rome"}}
Array#dig
然后在 h
:
上调用 Hash#dig
g = h.dig(:value)
#=> {:destination=>"Rome"}
最后,g
作为散列,Hash#dig
在 g
上调用 Hash#dig
:
g.dig(:destination)
#=> "Rome"
使用任何 dig
时都需要小心。假设
arr = [[1,2], [3,[4,5]]]
我们希望拉出现在被4
占用的对象。我们可以这样写
arr[1][1][0]
#=> 4
或
arr.dig(1,1,0)
#=> 4
现在假设 arr
更改如下:
arr = [[1,2]]
然后
arr[1][1][0]
#=> NoMethodError: undefined method `[]' for nil:NilClass
和
arr.dig(1,1,0)
#=> nil
两者都表明我们的代码中存在错误,因此引发异常比返回 nil
更可取,这可能会在一段时间内被忽视。
我正在尝试获取散列中的嵌套值。我试过使用 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
所需的 return 值为 "Rome"
。第二个表达式有效,但我想知道是否可以简化它。
我正在使用 Ruby v2.5 和 Rails v5.2.1.1。
dig(key, ...) → object
Extracts the nested value specified by the sequence of key objects by calling
dig
at each step, returningnil
if any intermediate step isnil
.
fetch(key [, default] ) → obj
fetch(key) {| key | block } → obj
Returns a value from the hash for the given key. If the key can't be found, there are several options: With no other arguments, it will raise a
KeyError
exception; if default is given, then that will be returned; if the optional code block is specified, then that will be run and its result returned.
看你的例子有什么不同:
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"
Hash#fetch is not relevant here. That's because fetch
is the same as Hash#[] 就像这里一样,fetch
只有一个参数。所以让我们专注于 dig
.
Ruby v2.3 中引入了三个 dig
方法家族:Hash#dig, Array#dig and OpenStruct#dig。这些方法的一个有趣之处在于它们会相互调用(但这在文档中没有解释,甚至在示例中也没有)。在你的问题中我们可以这样写:
response.dig(:results, 0, :value, :destination)
#=> "Rome"
response
是一个散列,因此 Hash#dig
计算 response[:results]
。如果它的值是 nil
那么表达式 returns 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
因此在 arr
上调用 Array#dig
,获取哈希
h = arr.dig(0)
#=> {:type=>"product_group", :value=>{:destination=>"Rome"}}
Array#dig
然后在 h
:
Hash#dig
g = h.dig(:value)
#=> {:destination=>"Rome"}
最后,g
作为散列,Hash#dig
在 g
上调用 Hash#dig
:
g.dig(:destination)
#=> "Rome"
使用任何 dig
时都需要小心。假设
arr = [[1,2], [3,[4,5]]]
我们希望拉出现在被4
占用的对象。我们可以这样写
arr[1][1][0]
#=> 4
或
arr.dig(1,1,0)
#=> 4
现在假设 arr
更改如下:
arr = [[1,2]]
然后
arr[1][1][0]
#=> NoMethodError: undefined method `[]' for nil:NilClass
和
arr.dig(1,1,0)
#=> nil
两者都表明我们的代码中存在错误,因此引发异常比返回 nil
更可取,这可能会在一段时间内被忽视。