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

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

在一行里。


当前回答

如果你正在使用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

其他回答

你可以用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,并让边界情况出现在代码中。

这也可以工作:hash[hey] = nil

如果你正在使用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

参见Ruby on Rails:删除多个散列键

hash.delete_if{ |k,| keys_to_delete.include? k }

如果你想使用纯Ruby(没有Rails),不想创建扩展方法(也许你只需要在一两个地方使用扩展方法,不想用大量的方法污染命名空间),不想在适当的地方编辑散列(也就是说,你像我一样是函数式编程的粉丝),你可以“选择”:

>> x = {:a => 1, :b => 2, :c => 3}
=> {:a=>1, :b=>2, :c=>3}
>> x.select{|x| x != :a}
=> {:b=>2, :c=>3}
>> x.select{|x| ![:a, :b].include?(x)}
=> {:c=>3}
>> x
=> {:a=>1, :b=>2, :c=>3}