Reputation: 5400
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
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
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
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