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

时间:2016-05-25 13:16:59

标签: 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

3 个答案:

答案 0 :(得分:9)

" 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

答案 1 :(得分:3)

enter image description here响应的基础上,如果你想要一个更灵活的get方法,你实际上可以从函数返回一个lambda并传递你想要获得的参数。这样可以很好地处理错误:

从上面的基础开始...

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

然后我们可以定义一个get_something函数,该函数获取元素路径的参数列表:

lambda_getter = get_something("x","y")
get_delta_by(hash1, hash2, &lambda_getter)

最后,我们使用&符号调用函数将lambda作为块传递:

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mongo="http://www.mulesoft.org/schema/mule/mongo" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:amqp="http://www.mulesoft.org/schema/mule/amqp" xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns:data-mapper="http://www.mulesoft.org/schema/mule/ee/data-mapper" xmlns:ftp="http://www.mulesoft.org/schema/mule/ee/ftp" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
    xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.6.1"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-current.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/ftp http://www.mulesoft.org/schema/mule/ee/ftp/current/mule-ftp-ee.xsd
http://www.mulesoft.org/schema/mule/ee/data-mapper http://www.mulesoft.org/schema/mule/ee/data-mapper/current/mule-data-mapper.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd
http://www.mulesoft.org/schema/mule/amqp http://www.mulesoft.org/schema/mule/amqp/current/mule-amqp.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/mongo http://www.mulesoft.org/schema/mule/mongo/current/mule-mongo.xsd">
    <context:property-placeholder location="mule-app.properties" />
    <configuration doc:name="Configuration">
        <expression-language autoResolveVariables="true">
            <import class="org.mule.util.StringUtils" />
            <import class="org.mule.util.ArrayUtils" />
        </expression-language>
    </configuration>
    <data-mapper:config name="test_mapper" transformationGraphPath="csv_to_json_1.grf" doc:name="test_mapper"/>
    <flow name="read-file" >
        <file:inbound-endpoint path="${file.unprocessed.location}" moveToPattern="#[message.inboundProperties['originalFilename']]" moveToDirectory="${file.processed.location}" responseTimeout="10000" doc:name="Files" mimeType="text/csv" >
            <file:filename-regex-filter pattern="test.csv" caseSensitive="true"/>
        </file:inbound-endpoint>
        <object-to-string-transformer doc:name="Object to String"/>
        <splitter expression="#[rows=StringUtils.split(message.payload,'\n\r'); ArrayUtils.subarray(rows,1,rows.size())]" doc:name="Splitter"/>
        <set-property propertyName="testFilename" value="#[flowVars.originalFilename]" doc:name="Set Filename"/>
        <choice doc:name="Choice">
            <when expression="#[message.outboundProperties.'testFilename'=='test.csv']">
                <data-mapper:transform config-ref="CSV_To_JSON" doc:name="CSV To JSON"/>
            </when>
            <otherwise>
                <logger level="INFO" doc:name="Logger"/>
            </otherwise>
        </choice>
        <object-to-string-transformer doc:name="Object to String"/>
        <logger level="INFO" doc:name="Logger"/>
    </flow>
</mule>

最后一点可以是一个班轮......但为了清楚起见,将其写成两个。

答案 2 :(得分:1)

在Ruby 2.3中,如果符合您的需要,您可以使用Hash#dig方法。

hash1.dig("x", "y") - hash2.dig("x", "y")
#=> 8