在代码大战中找到这个作为解决方案之一。有人可以向我解释" args.reduce(self)"适用于此代码;之后的街区是有道理的。
config = { :files => { :mode => 0x777 }, :name => "config" }
class Hash
def get_value( default, *args )
args.empty? ? default : args.reduce(self) { |acum, key| acum.fetch(key) } rescue default
end
end
config.get_value("", :files,:mode)
答案 0 :(得分:2)
假设我们执行
{ :a=>{:b=>{:c=>3 } } }.get_value(4, :a, :b, :c)
以便在方法
中default #=> 4
args #=> [:a, :b, :c]
self #=> { :a=>{:b=>{:c=>3 } } }
然后我们执行以下 1 :
args.empty? ? default : args.reduce(self) { |acum, key| acum.fetch(key) } rescue default
#=> [:a, :b, :c].empty? ? 4 : [:a, :b, :c].reduce({ :a=>{:b=>{:c=>3 } } }) { |acum, key|
# acum.fetch(key) } rescue 4
#=> 3
如果args #=> [:a, :b]
,我们执行以下操作:
[:a, :b].empty? ? 4 : [:a, :b].reduce({ :a=>{:b=>{:c=>3 } } }) { |acum, key|
acum.fetch(key) } rescue 4
#=> {:c=>3}
如果args #=> [:a, :b, :cat]
,则会引发KeyError
个异常,内联rescue
会返回default
的值:
[:a, :b, :cat].empty? ? 4 : [:a, :b, :cat].reduce({ :a=>{:b=>{:c=>3 } } }) { |acum, key|
acum.fetch(key) } rescue 4
#=> 4
如果args #=> []
,[].empty?
为true
,则会再次返回default
的值:
[].empty? ? 4 : [].reduce({ :a=>{:b=>{:c=>3 } } }) { |acum, key|
acum.fetch(key) } rescue 4
#=> 4
幸运的是,我们不再需要处理Ruby 2.3.0中给出Hash#dig这样的废话,允许我们编写以下内容。
class Hash
def get_value( default, *keys )
keys.empty? ? default : dig(*keys) || default
end
end
{ :a=>{:b=>{:c=>3 } } }.get_value(4, :a, :b, :c)
#=> 3
{ :a=>{:b=>{:c=>3 } } }.get_value(4, :a, :b)
#=> {:c=>3}
{ :a=>{:b=>{:c=>3 } } }.get_value(4, :a, :b, :cat)
#=> 4
{ :a=>{:b=>{:c=>3 } } }.get_value(4)
#=> 4
请注意,dig
的默认接收方为self
。
1请注意,该代码的作者可以编写...args.reduce(self) { |acum, key| acum.fetch(key) } rescue default
而不是...args.reduce(self) { |acum, key| acum.fetch(key, default) }
。见Hash#fetch。
答案 1 :(得分:1)
它假定self
是一个哈希嵌套,并将args
视为一系列键,以深入深入到该哈希嵌套中。
答案 2 :(得分:0)
self
是config
哈希本身。
reduce
接受self
的参数(因此原始config
哈希)。
然后,第一次迭代的accum
将被赋予该参数(原始config
哈希)。
在每次迭代中,accum
将使用args
的每个键的(嵌套)值重新分配。
答案 3 :(得分:0)
让我们看一下以下示例。
config = {
:files => { :mode => 0x777 },
:name => "config"
}
[:files, :mode].reduce(config) { |hash, key|
# The value for the current key, which can be another hash.
newhash = hash.fetch(key)
# Log each iteration here to see what's happening.
# p newhash
# Return the value for next iteration.
newhash
}
输出为HEX值0x777
,由Ruby转换为小数1911
。
在使用args.reduce(self)
的示例中,self
是作为块的第一个参数传递的初始值,即config
哈希本身。数组混合在Enumerable中,而 reduce 来自的地方。更多信息:http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-reduce
对于 reduce 的每次迭代,块变量包含以下值:
hash
包含{ :files => { :mode => 0x777 }, :name => "config" }
;这是 config 哈希本身。key
包含:files
;数组的第一项。newhash
包含{:mode=>1911}
,我们将其返回并成为下一次迭代的第一个参数。hash
包含{:mode=>1911}
,因为我们在上一次迭代中返回了 newhash 。key
包含:mode
;数组的第二项。newhash
包含1911
;减少迭代完成,这是最终值。