Ruby 试图理解Hash#merge与Procs的实现
试图理解这个问题。我正在创建一个名为hash#my#u merge的hash#merge的我自己的验证,它可以接受一个进程。我试图了解它的功能:Ruby 试图理解Hash#merge与Procs的实现,ruby,hash,merge,Ruby,Hash,Merge,试图理解这个问题。我正在创建一个名为hash#my#u merge的hash#merge的我自己的验证,它可以接受一个进程。我试图了解它的功能: self.each do |k,v| newhash[k]=hash[k] ? prc.call(k,v,hash[k]): v end 它看起来像一个三元运算,但newhash[k]=hash[k]不是真/假语句吗?提示及问题的其余部分如下: class Hash # Hash#merge takes a proc that accepts t
self.each do |k,v|
newhash[k]=hash[k] ? prc.call(k,v,hash[k]): v
end
它看起来像一个三元运算,但newhash[k]=hash[k]不是真/假语句吗?提示及问题的其余部分如下:
class Hash
# Hash#merge takes a proc that accepts three arguments: a key and the two
# corresponding values in the hashes being merged. Hash#merge then sets that
# key to the return value of the proc in a new hash. If no proc is given,
# Hash#merge simply merges the two hashes.
#
# Write a method with the functionality of Hash#merge. Your Hash#my_merge
method
# should optionally take a proc as an argument and return a new hash. If a
proc
# is not given, your method should provide default merging behavior. Do not
use
# Hash#merge in your method.
def my_merge(hash, &prc)
prc ||=Proc.new{|k,oldval,newval|}
newhash=Hash.new
self.each do |k,v|
newhash[k]=hash[k] ? prc.call(k,v,hash[k]): v
end
hash.each do |k,v|
newhash[k]=v if newhash[k].nil?
end
newhash
end
end
任何帮助都将不胜感激。谢谢 你的误解是一条三元线,但操作顺序不是你所期望的。当Ruby看到:
newhash[k]=hash[k] ? prc.call(k,v,hash[k]): v
它将其视为
newhash[k]= (hash[k] ? prc.call(k,v,hash[k]): v)
因此,如果hash[k]
是真值-y,则调用proc并将结果分配给newhash[k]
;否则,将v
分配给newhash[k]
通过查看文件,您可以看到Ruby是这样看待这一行的,该文件包含(在一堆其他操作符中):
?,:
改装救援
=、+=、-=,等等
因此,三元运算符的优先级高于赋值运算符
另外值得注意的是,在Ruby中,
newhash[k]=hash[k]
是一个true/false语句,因为赋值返回被赋值的内容:
a = 1 # => 1
a = nil # => nil
Ruby中除了false
和nil
之外的所有内容都被视为一个truth-y值,您可以执行以下操作:
if a = 2
puts "truthy"
end
# outputs 'truthy'
及
通过适当的括号,您可以在三元结构中使用它:
(a = 1) ? 'truthy' : 'falsey' # => 'truthy'
(a = nil) ? 'truthy' : 'falsey' # => 'falsey'
不过,这可能会让人困惑(通常在条件中你会看到
==
而不是=
,事实上,我的Ruby给了我一个警告,我在条件中使用的是=
,而不是=
);但是这是可以做到的,你的误解是三元的,但是操作的顺序不是你所期望的。当Ruby看到:
newhash[k]=hash[k] ? prc.call(k,v,hash[k]): v
它将其视为
newhash[k]= (hash[k] ? prc.call(k,v,hash[k]): v)
因此,如果hash[k]
是真值-y,则调用proc并将结果分配给newhash[k]
;否则,将v
分配给newhash[k]
通过查看文件,您可以看到Ruby是这样看待这一行的,该文件包含(在一堆其他操作符中):
?,:
改装救援
=、+=、-=,等等
因此,三元运算符的优先级高于赋值运算符
另外值得注意的是,在Ruby中,
newhash[k]=hash[k]
是一个true/false语句,因为赋值返回被赋值的内容:
a = 1 # => 1
a = nil # => nil
Ruby中除了false
和nil
之外的所有内容都被视为一个truth-y值,您可以执行以下操作:
if a = 2
puts "truthy"
end
# outputs 'truthy'
及
通过适当的括号,您可以在三元结构中使用它:
(a = 1) ? 'truthy' : 'falsey' # => 'truthy'
(a = nil) ? 'truthy' : 'falsey' # => 'falsey'
不过,这可能会让人困惑(通常在条件中你会看到
==
而不是=
,事实上,我的Ruby给了我一个警告,我在条件中使用的是=
,而不是=
);但是这是可以做到的,当你的核心问题是以那种方式使用三元时,真正的问题是实际解决方案过于复杂
如果您刚刚开始使用Ruby,请尽量避免使用诸如三元语句之类的语句,以使代码尽可能简单明了。例如,以下各项的作用是什么:
a = nil
a = true ? :yes : :no
如果您认为答案是“a
已分配:yes
”,那么您的阅读是正确的。如果您认为“a
被赋值true
”,那么您忘记了三元?
的赋值优先级高于=
,因此它首先发生
如果你这样看,情况就不一样了:
if (a = true)
:yes
else
:no
end
或者另一种解释明确指出:
a =
if (true)
:yes
else
:no
end
即使对编程有了基本的了解,这两者的结果也会立即显现出来。如果真的很晚了,而且你正试图修复一个bug,但是你自己的代码太复杂了,你无法理解,那么这也很方便
也就是说,经过返工的解决方案如下所示:
class Hash
def my_merge(hash)
# Figure out all the keys that might show up in this merge in advance.
keys = (self.keys + hash.keys).uniq
newhash = { }
# Try all possible keys and evaluate what the result should be
keys.each do |k|
newhash[k] =
if (block_given?)
yield(k, self[k], hash[k])
elsif (self.has_key?(k))
self[k]
else
hash[k]
end
end
newhash
end
end
您可以利用if
在Ruby中实际返回值的方式来简化这个问题,并保持内部逻辑非常清晰
需要注意的一点是,当您使用Hash.new
时,您可能指的是{}
。正式声明保留用于Hash.new(0)
或Hash.new{| h,k | h[k]=[]}
等内容,其中第一个设置静态默认值,第二个设置计算默认值。如果没有设置默认值,请不要使用显式初始值设定项。这只会增加噪音
您还可以更好地利用Ruby的内置功能,这些功能可以显著减少所需的临时变量数量,以及实现这样的转换所需的实际工作量。例如,稍微整理一下,你会发现:
class Hash
def my_merge(hash)
(self.keys + hash.keys).uniq.map do |k|
[
k,
if (block_given?)
yield(k, self[k], hash[k])
elsif (self.has_key?(k))
self[k]
else
hash[k]
end
]
end.to_h
end
end
这是相当精简的,最大的代码块是
merge
实现,应该是这样的,而不是所有的设置和清理代码。虽然您的核心问题是以这种方式使用三元结构,但真正的问题是实际解决方案过于复杂
如果您刚刚开始使用Ruby,请尽量避免使用诸如三元语句之类的语句,以使代码尽可能简单明了。例如,以下各项的作用是什么:
a = nil
a = true ? :yes : :no
如果您认为答案是“a
已分配:yes
”,那么您的阅读是正确的。如果您认为“a
被赋值true
”,那么您忘记了三元?
的赋值优先级高于=
,因此它首先发生
如果你这样看,情况就不一样了:
if (a = true)
:yes
else
:no
end
或者另一种解释明确指出:
a =
if (true)
:yes
else
:no
end
即使对编程有了基本的了解,这两者的结果也会立即显现出来。如果真的很晚了,而且你正试图修复一个bug,但是你自己的代码太复杂了,你无法理解,那么这也很方便
话虽如此,一个重新设计的