添加一对新的哈希,我做:
{:a => 1, :b => 2}.merge!({:c => 3}) #=> {:a => 1, :b => 2, :c => 3}
是否有类似的方法从哈希中删除键?
如此:
{:a => 1, :b => 2}.reject! { |k| k == :a } #=> {:b => 2}
但我希望有这样的东西:
{:a => 1, :b => 2}.delete!(:a) #=> {:b => 2}
重要的是,返回值将是剩余的散列,所以我可以这样做:
foo(my_hash.reject! { |k| k == my_key })
在一行里。
#in lib/core_extensions.rb
class Hash
#pass single or array of keys, which will be removed, returning the remaining hash
def remove!(*keys)
keys.each{|key| self.delete(key) }
self
end
#non-destructive version
def remove(*keys)
self.dup.remove!(*keys)
end
end
#in config/initializers/app_environment.rb (or anywhere in config/initializers)
require 'core_extensions'
我已经设置好了,所以.remove返回一个删除键的散列副本,而remove!修改哈希本身。这与ruby的约定是一致的。从控制台
>> hash = {:a => 1, :b => 2}
=> {:b=>2, :a=>1}
>> hash.remove(:a)
=> {:b=>2}
>> hash
=> {:b=>2, :a=>1}
>> hash.remove!(:a)
=> {:b=>2}
>> hash
=> {:b=>2}
>> hash.remove!(:a, :b)
=> {}
如果你正在使用Ruby 2,你可以使用改进,而不是猴子补丁或不必要地包括大型库:
module HashExtensions
refine Hash do
def except!(*candidates)
candidates.each { |candidate| delete(candidate) }
self
end
def except(*candidates)
dup.remove!(candidates)
end
end
end
您可以在不影响程序其他部分的情况下使用此特性,也不必包含大型外部库。
class FabulousCode
using HashExtensions
def incredible_stuff
delightful_hash.except(:not_fabulous_key)
end
end
onlineer普通红宝石,它只适用于红宝石> 1.9.x:
1.9.3p0 :002 > h = {:a => 1, :b => 2}
=> {:a=>1, :b=>2}
1.9.3p0 :003 > h.tap { |hs| hs.delete(:a) }
=> {:b=>2}
方法总是返回被调用的对象…
否则,如果你需要active_support/core_ext/hash(这在每个Rails应用程序中都是自动需要的),你可以根据需要使用以下方法之一:
➜ ~ irb
1.9.3p125 :001 > require 'active_support/core_ext/hash' => true
1.9.3p125 :002 > h = {:a => 1, :b => 2, :c => 3}
=> {:a=>1, :b=>2, :c=>3}
1.9.3p125 :003 > h.except(:a)
=> {:b=>2, :c=>3}
1.9.3p125 :004 > h.slice(:a)
=> {:a=>1}
Except使用黑名单方法,因此它删除了所有作为参数列出的键,而slice使用白名单方法,因此它删除了所有没有作为参数列出的键。这些方法也存在bang版本(除了!和slice!),它们修改给定的哈希,但它们的返回值不同,它们都返回哈希。它代表slice删除的键!还有为except保留的钥匙!:
1.9.3p125 :011 > {:a => 1, :b => 2, :c => 3}.except!(:a)
=> {:b=>2, :c=>3}
1.9.3p125 :012 > {:a => 1, :b => 2, :c => 3}.slice!(:a)
=> {:b=>2, :c=>3}