I have a hash that contains 2 arrays of hashes
h = {
"budget_options"=>[
{"amount"=>"1.0", "text"=>"budget options"},
{"amount"=>"2.0", "most_popular"=>"true", "text"=>"budget options"},
{"amount"=>"3.0", "text"=>"budget options"}
],
"pcb_budget_options"=>[
{"amount"=>"1.0"},
{"amount"=>"0.0"},
{"amount"=>"-1.0", "most_popular"=>"true"}
]
}
I just want to convert "most_popular" value from string to boolean I tried to do this but it ends up with n3 time complexity.
Is there a built-in method to do this? Any kind of help will be appriciated.
CodePudding user response:
I think this does what you want. I have not calculated the O of it. I used the Marshal#dump/load trick to do a deep copy of the object before manipulating it.
mp = "most_popular"
obj = Marshal.load(Marshal.dump(h))
obj.each_key {|k| obj[k].each {|v| v[mp] = v[mp] == "true" ? true : false if v[mp] }}
Also see Cary's comment below for a slightly more terse version of the inner block.
CodePudding user response:
If you do not wish to mutate h
you can write
h.transform_values do |arr|
arr.map do |g|
g.merge({})
.tap { |f| f["most_popular"] = f["most_popular"]=="true" if f.key?("most_popular") }
end
end
#=> {
# "budget_options"=>[
# {"amount"=>"1.0", "text"=>"budget options"},
# {"amount"=>"2.0", "most_popular"=>true, "text"=>"budget options"},
# {"amount"=>"3.0", "text"=>"budget options"}
# ],
# "pcb_budget_options"=>[
# {"amount"=>"1.0"},
# {"amount"=>"0.0"},
# {"amount"=>"-1.0", "most_popular"=>true}
# ]
# }
The purpose of g.merge({})
is to avoid mutating the inner hashes. See Hash#transform_values, Hash#merge and Object#tap.