kakubei
kakubei

Reputation: 5400

Remove keys in hash not in array

I can't find a way to remove keys from a hash that are not in a given array of key names. I read that I can use except or slice, but how can I feed them a list of the key names I want to keep? So for example, if I had this hash:

entry = {:title=>"casablanca", :media=>"dvd", :localeLanguage=>"en", :imdb=>"", :freebase=>"", :originalTitle => 'casablanca', :season=> '1', :episode => '3'}

and I only wanted to keep, say, :title, :media and :localeLanguage, how could I keep only those values whose key names I specify?

Upvotes: 12

Views: 7978

Answers (3)

Benjamin Crouzier
Benjamin Crouzier

Reputation: 41965

In Rails 4+, use slice:

entry = {:title=>"casablanca", :media=>"dvd", :localeLanguage=>"en", :imdb=>"", :freebase=>"", :originalTitle => 'casablanca', :season=> '1', :episode => '3'}
keepers = [:title, :media, :localeLanguage]

entry.slice(*keepers)
# => {:title=>"casablanca", :media=>"dvd", :localeLanguage=>"en"}

Shorter version (with same result):

entry.slice(*%i(title media localeLanguage))

Use slice! to modify your hash in-place.

Upvotes: 26

Mark Thomas
Mark Thomas

Reputation: 37517

I'd use keep_if (requires 1.9.2).

keepers = [:title, :media, :localeLanguage]

entry.keep_if {|k,_| keepers.include? k }

#=> {:title=>"casablanca", :media=>"dvd", :localeLanguage=>"en"}      

Upvotes: 22

Wayne Conrad
Wayne Conrad

Reputation: 108179

In Ruby 1.9.3:

entry = entry.select do |key, value|
  [:title, :media, :localeLanguage].include?(key)
end
p entry
# => {:title=>"casablanca", :media=>"dvd", :localeLanguage=>"en"}

In Ruby 1.8.7, Hash#select returns an array of arrays, so use Hash[] to turn that array into a hash:

entry = Hash[
  entry.select do |key, value|
    [:title, :media, :localeLanguage].include?(key)
  end
]
# => {:media=>"dvd", :localeLanguage=>"en", :title=>"casablanca"}

The difference in order is because, in Ruby 1.8.7, Hashes are unordered.

Upvotes: 4

Related Questions