添加一对新的哈希,我做:

{: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 })

在一行里。


当前回答

试试except!方法。

{:a => 1, :b => 2}.except!(:a)   #=> {:b => 2}

其他回答

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} 

为什么不直接使用:

hash.delete(key)

哈希现在是您正在寻找的“剩余哈希”。

在纯Ruby中:

{:a => 1, :b => 2}.tap{|x| x.delete(:a)}   # => {:b=>2}

这是一种单行的方式,但可读性不强。建议用两行代替。

use_remaining_hash_for_something(Proc.new { hash.delete(:key); hash }.call)

你可以用except!来自facets gem:

>> require 'facets' # or require 'facets/hash/except'
=> true
>> {:a => 1, :b => 2}.except(:a)
=> {:b=>2}

原来的哈希值不会改变。

编辑:正如Russel所说,facets有一些隐藏的问题,并且与ActiveSupport不完全兼容api。另一方面,ActiveSupport不像facet那样完整。最后,我将使用AS,并让边界情况出现在代码中。