我想尽可能简洁地计算具有相同结构的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
答案 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)
在响应的基础上,如果你想要一个更灵活的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