How to remove a key from Hash and get the remainin

2019-01-15 23:35发布

To add a new pair to Hash I do:

{:a => 1, :b => 2}.merge!({:c => 3})   #=> {:a => 1, :b => 2, :c => 3}

Is there a similar way to delete a key from Hash ?

This works:

{:a => 1, :b => 2}.reject! { |k| k == :a }   #=> {:b => 2}

but I would expect to have something like:

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

It is important that the returning value will be the remaining hash, so I could do things like:

foo(my_hash.reject! { |k| k == my_key })

in one line.

13条回答
我只想做你的唯一
2楼-- · 2019-01-16 00:14

You can use except! from the facets gem:

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

The original hash does not change.

EDIT: as Russel says, facets has some hidden issues and is not completely API-compatible with ActiveSupport. On the other side ActiveSupport is not as complete as facets. In the end, I'd use AS and let the edge cases in your code.

查看更多
Luminary・发光体
3楼-- · 2019-01-16 00:14

This would also work: hash[hey] = nil

查看更多
时光不老,我们不散
4楼-- · 2019-01-16 00:19

Why not just use:

hash.delete(key)
查看更多
甜甜的少女心
5楼-- · 2019-01-16 00:19

It's was great if delete return the delete pair of the hash. I'm doing this:

hash = {a: 1, b: 2, c: 3}
{b: hash.delete(:b)} # => {:b=>2}
hash  # => {:a=>1, :c=>3} 
查看更多
做个烂人
6楼-- · 2019-01-16 00:20

Rails has an except/except! method that returns the hash with those keys removed. If you're already using Rails, there's no sense in creating your own version of this.

class Hash
  # Returns a hash that includes everything but the given keys.
  #   hash = { a: true, b: false, c: nil}
  #   hash.except(:c) # => { a: true, b: false}
  #   hash # => { a: true, b: false, c: nil}
  #
  # This is useful for limiting a set of parameters to everything but a few known toggles:
  #   @person.update(params[:person].except(:admin))
  def except(*keys)
    dup.except!(*keys)
  end

  # Replaces the hash without the given keys.
  #   hash = { a: true, b: false, c: nil}
  #   hash.except!(:c) # => { a: true, b: false}
  #   hash # => { a: true, b: false }
  def except!(*keys)
    keys.each { |key| delete(key) }
    self
  end
end
查看更多
Ridiculous、
7楼-- · 2019-01-16 00:20

If you want to use pure Ruby (no Rails), don't want to create extension methods (maybe you need this only in one or two places and don't want to pollute namespace with tons of methods) and don't want to edit hash in place (i.e., you're fan of functional programming like me), you can 'select':

>> 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}
查看更多
登录 后发表回答