Reputation: 309
I have a hash like this:
entity = {1=> nil, 2 => {3 => nil, 4 => 1}}
I wrote a function which can remove the null values of the given entity using recursion.
def clear_null_values(entity)
entity.each do |key, value|
if value == nil || value.blank?
entity.delete(key)
elsif value.is_a? Hash
clear_null_values(value)
entity.delete(key) if value.blank?
end
end
end
And also I need the original entity as well for other purposes. So I duplicated the hash variable and then cleared the null values.
final_entity = entity.dup
clear_null_values(entity)
puts entity
puts final_entity
Result:
{2 => {4 => 1}}
{1=> nil, 2 => {4 => 1}} # the nested values are overwritten.
Ideally, the final_entity should be the same as original entity.
Question1: Why is the entity.dup
copying only outerhash?
Question2: How to make final_entity the exactly copy of original entity i.e., even if we modify entity then also final_entity shouldn't change?
Upvotes: 0
Views: 257
Reputation: 110675
It would be cleaner, in my opinion, to compute the hash stripped of nil
values by operating on entities
directly, rather than on a copy of it.
def clear_null_values(entity)
entity.each_with_object({}) do |(k,v),h|
next if v.nil?
h[k] = Hash === v ? clear_null_values(v) : v
end
end
entities = { 1=>nil, 2=>{ 3=>nil, 4=>1 } }
clear_null_values entities
#=> {2=>{4=>1}}
We can confirm entities
was not mutated.
entities
#=> {1=>nil, 2=>{3=>nil, 4=>1}}
Upvotes: 0
Reputation: 66837
Try using deep_dup
instead, your original code only dup
-ed the outermost hash.
final_entity = entity.deep_dup
clear_null_values(entity)
puts entity
puts final_entity
Outputs:
{2=>{4=>1}}
{1=>nil, 2=>{3=>nil, 4=>1}}
Note: Rails also adds Hash#compact
, which you could use to simplify clear_null_values
.
Upvotes: 5