Reputation: 2391
In a method I get a list of options passed in. Some are related to a particular scope. I want to store those special keys in another hash to be able to pass it to a different method, and delete them from the original hash.
(I'm actually writing a rails simple_form custom input, but that doesn't matter)
I have the following code:
all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }
my_keys = [:key1, :key2, :key3, :key4]
my_options = all_options.select {|k,v| my_keys.include?(k)}
all_options.delete_if {|k,v| my_keys.include?(k)}
# expecting
my_options == { :key1 => 1, :key2 => 2 }
all_options == { :something_else => 42 }
Now my question is there a better, i.e. smarter way of doing it?
Maybe it's just sugar, but I want to know.
Upvotes: 1
Views: 986
Reputation: 1
all_options = { key1: 1, key2: 2, something_else: 42 }
my_keys = [:key1, :key2, :key3, :key4]
my_options = my_keys.each_with_object({}) do |key, hash|
hash[key] = all_options.delete(key) if all_options.key?(key)
end
Upvotes: 0
Reputation: 2677
all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }
my_keys = [:key1, :key2, :key3, :key4]
my_options = my_keys.inject({}) {|h,k| h[k] = all_options.delete(k) if all_options.key?(k);h}
all_options
# => {:something_else=>42}
my_options
# => {:key1=>1, :key2=>2}
here's a way to improve Ju Liu's answer:
all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }
my_keys = [:key1, :key2, :key3, :key4]
my_options = all_options.extract!(*my_keys).keep_if {|k,v| v}
all_options
# => {:something_else=>42}
my_options
# => {:key1=>1, :key2=>2}
however you'll lose your options if any key in a all_options
hash has an actual value of nil
or false
(don't know if you need to keep them):
all_options = { :key1 => 1, :key2 => nil, :something_else => 42 }
here's a way to keep false
's
my_options = all_options.extract!(*my_keys).keep_if {|k,v| !v.nil?}
p.s. it would be possible to keep all values including nil
s if you store the keys from all_options
:
all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }
all_keys = all_options.keys
my_keys = [:key1, :key2, :key3, :key4]
my_options = all_options.extract!(*my_keys).keep_if {|k,v| all_keys.include?(k)}
all_options
# => {:something_else=>42}
my_options
# => {:key1=>1, :key2=>2}
Upvotes: 1
Reputation: 118299
I know only Ruby. So here my Ruby approach :
all_options = { :key1 => 1, :key2 => 2, :something_else => 42 }
my_keys = [:key1, :key2, :key3, :key4]
#below statement is your my_options
Hash[my_keys.map{|i| [i,all_options.delete(i)] if all_options.has_key? i }.compact]
# => {:key1=>1, :key2=>2}
all_options
# => {:something_else=>42}
Upvotes: 1