繁体   English   中英

传递一个在Ruby中将参数作为参数的方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM