How can the values from one hash be copied into another, but only for the keys that exist in both hashes?
Minimal example
h1 = {a: 10, b: 20, c: 30}
h2 = {a: nil, c: nil}
## desired result
{a: 10, c: 30}
I've solved with a 'manual' approach - i.e. {a: h1[:a], c: h1[:c]}
- but it's verbose and looks worse the more keys there are. I'm sure there's something (much) more elegant?
CodePudding user response:
The "manual" approach with a loop would look something like this
h1.each do |k, v|
h2[k] = v if h2.include? k
end
If your goal is to create a new hash, rather than modifying an existing one, you can use filter
(called select
in older versions of Ruby)
h1.filter { |k, v| h2.include? k }
Or if you want to modify h1
to only have the keys from k2
, you can use filter!
(called select!
in older versions), which works like filter
but modifies in-place.
h1.filter! { |k, v| h2.include? k }
CodePudding user response:
One way is to use the form of Hash#merge that takes a block that computes the values of keys that are present in both hashes being merged:
h1 = {a: 10, b: 20, c: 30}
h2 = {a: nil, c: nil}
h2.merge(h2) { |k,*| h1[k] }
#=> {:a=>10, :c=>30}
As h2
is merged with itself, the block is invoked for every key.
One advantage of this approach is that it avoids the need for a linear search of keys in h2
for each key in h1
. By contrast, key lookups (to obtain h1[k]
) are quite fast.