我承认从一条路开始,然后想知道它会带我去哪里。这可能不是确定哈希中是否存在键/值对的最佳方法(如何改进@Jordan 的答案?),但我在此过程中学到了一些东西。
代码
def pair_present?(h,k,v)
Enumerable.instance_method(:include?).bind(h).call([k,v])
end
示例
h = { "a"=>1, "d"=>2, "f"=>35 }
pair_present?(h,'a',1)
#=> true
pair_present?(h,'f',36)
#=> false
pair_present?(h,'hippopotamus',2)
#=> false
讨论
我们当然可以将哈希转换为数组,然后应用Array#include?:
h.to_a.include?(['a', 1])
#=> true
但这有创建临时数组的缺点。如果Hash 类有这样的实例方法就好了,但它没有。有人可能会认为Hash#include? 可能用于此目的,但它只需要一个参数,一个键。1。
Enumerable#include? 方法做我们想做的事,当然Hash includes Enumerable 模块。我们可以通过多种方式调用该方法。
将Enumerable#include? 绑定到哈希并调用它
这当然是我的回答:
Enumerable.instance_method(:include?).bind(h).call([k,v])
使用方法Method#super_method,在v2.2中引入。
h.method(:include?).super_method.call(['a',1])
#=> true
h.method(:include?).super_method.call(['a',2])
#=> false
请注意:
h.method(:include?).super_method
#=> #<Method: Object(Enumerable)#include?>
做alias_method/remove_method旋转木马
Hash.send(:alias_method, :temp, :include?)
Hash.send(:remove_method, :include?)
h.include?(['a',1])
#=> true
h.include?(['a',2])
#=> false
Hash.send(:alias_method, :include?, :temp)
Hash.send(:remove_method, :temp)
将哈希转换为枚举器并调用Enumerable#include?
h.to_enum.include?(['a',1])
#=> true
h.to_enum.include?(['a',2])
#=> false
这是有效的,因为 Enumerator 类也是 includes Enumerable。
1 Hash#include? 与 Hash#key? 和 Hash#has_key? 相同。这让我想知道为什么 include? 不用于目前的目的,因为确定哈希是否具有给定的密钥已被很好地覆盖。