[英]Passing a method that takes arguments as an argument in Ruby
我想尽可能简洁地计算具有相同结构的2个哈希值内的各种值的差异。 这是我想要比较的数据的简化示例:
hash1 = {"x" => { "y" => 20 } }
hash2 = {"x" => { "y" => 12 } }
我有一个非常简单的方法来获取我想要比较的值。 实际上,散列可以嵌套比这些示例更深,所以这主要是为了保持代码可读:
def get_y(data)
data["x"]["y"]
end
我想创建一个方法来计算2个值之间的差异,并且可以将get_y
这样的方法作为参数,允许我重复使用哈希中任何值的代码。 我希望能够调用这样的东西,我不知道如何编写方法get_delta
:
get_delta(hash1, hash2, get_y) # => 8
“Ruby方式”将传递一个块:
def get_delta_by(obj1, obj2)
yield(obj1) - yield(obj2)
end
hash1 = {"x" => { "y" => 20 } }
hash2 = {"x" => { "y" => 12 } }
get_delta_by(hash1, hash2) { |h| h["x"]["y"] }
#=> 8
方法可以通过以下方式(间接)传递:
def get_y(data)
data["x"]["y"]
end
get_delta_by(hash1, hash2, &method(:get_y))
#=> 8
基于Stefan的响应,如果你想要一个更灵活的get方法,你实际上可以从函数返回一个lambda并传递你想要得到的参数。 这样可以很好地处理错误:
从上面的基础知识开始......
def get_delta_by(obj1, obj2)
yield(obj1) - yield(obj2)
end
hash1 = {"x" => { "y" => 20 } }
hash2 = {"x" => { "y" => 12 } }
get_delta_by(hash1, hash2) { |h| h["x"]["y"] }
然后我们可以定义一个get_something函数,该函数获取元素路径的参数列表:
def get_something(*args)
lambda do |data|
args.each do |arg|
begin
data = data.fetch(arg)
rescue KeyError
raise RuntimeError, "KeyError for #{arg} on path #{args.join(',')}"
end
end
return data
end
end
最后,我们使用&符号调用函数将lambda作为块传递:
lambda_getter = get_something("x","y")
get_delta_by(hash1, hash2, &lambda_getter)
最后一点可以是一个班轮......但为了清楚起见,将其写成两个。
在Ruby 2.3中,如果满足您的需求,您可以使用Hash#dig
方法。
hash1.dig("x", "y") - hash2.dig("x", "y")
#=> 8
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.