检测哈希中是否存在键值对
Detecting if a key-value pair exists within a hash
我找不到确定哈希中是否存在键值对的方法。
h4 = { "a" => 1, "d" => 2, "f" => 35 }
我可以使用 Hash#has_value?
和 Hash#has_key?
分别查找有关键或值的信息,但如何检查是否存在一对?
我所追求的伪代码:
if h4.contains_pair?("a", 1)
只需使用这个:
h4['a'] == 1
这对我来说似乎太过分了,但你可以用这样的方法对 Hash 进行猴子修补:
class Hash
def contains_pair?(key, value)
key?(key) && self[key] == value
end
end
如何使用枚举any?
h4 = { "a" => 1, "d" => 2, "f" => 35 }
h4.any? {|k,v| k == 'a' && v == 1 }
我承认开始走一条路,然后想知道它会把我带到哪里。这可能不是确定散列中是否存在 key/value 对的最佳方法(如何改进@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
但这有创建临时数组的缺点。如果 class Hash
有这样的实例方法就好了,但它没有。有人可能认为 Hash#include? 可能用于此目的,但它只需要一个参数,一个键。1.
方法 Enumerable#include? 做我们想要的,当然 Hash
include
是 Enumerable
模块。我们可以通过多种方式调用该方法。
将Enumerable#include?
绑定到哈希并调用它
这当然是我的回答:
Enumerable.instance_method(:include?).bind(h).call([k,v])
使用v2.2中引入的方法Method#super_method。
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
这是有效的,因为 class Enumerator 也 include
s Enumerable
。
1 Hash#include?
与 Hash#key? and Hash#has_key? 相同。这让我想知道为什么 include?
不用于当前目的,因为确定哈希是否具有给定密钥已被很好地覆盖。
我找不到确定哈希中是否存在键值对的方法。
h4 = { "a" => 1, "d" => 2, "f" => 35 }
我可以使用 Hash#has_value?
和 Hash#has_key?
分别查找有关键或值的信息,但如何检查是否存在一对?
我所追求的伪代码:
if h4.contains_pair?("a", 1)
只需使用这个:
h4['a'] == 1
这对我来说似乎太过分了,但你可以用这样的方法对 Hash 进行猴子修补:
class Hash
def contains_pair?(key, value)
key?(key) && self[key] == value
end
end
如何使用枚举any?
h4 = { "a" => 1, "d" => 2, "f" => 35 }
h4.any? {|k,v| k == 'a' && v == 1 }
我承认开始走一条路,然后想知道它会把我带到哪里。这可能不是确定散列中是否存在 key/value 对的最佳方法(如何改进@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
但这有创建临时数组的缺点。如果 class Hash
有这样的实例方法就好了,但它没有。有人可能认为 Hash#include? 可能用于此目的,但它只需要一个参数,一个键。1.
方法 Enumerable#include? 做我们想要的,当然 Hash
include
是 Enumerable
模块。我们可以通过多种方式调用该方法。
将Enumerable#include?
绑定到哈希并调用它
这当然是我的回答:
Enumerable.instance_method(:include?).bind(h).call([k,v])
使用v2.2中引入的方法Method#super_method。
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
这是有效的,因为 class Enumerator 也 include
s Enumerable
。
1 Hash#include?
与 Hash#key? and Hash#has_key? 相同。这让我想知道为什么 include?
不用于当前目的,因为确定哈希是否具有给定密钥已被很好地覆盖。