Reputation: 169
I have a nested hash of data:
munsters = {
"Herman" => { "age" => 32, "gender" => "male" },
"Lily" => { "age" => 30, "gender" => "female" },
"Grandpa" => { "age" => 402, "gender" => "male" },
"Eddie" => { "age" => 10, "gender" => "male" },
"Marilyn" => { "age" => 23, "gender" => "female"}
}
I want to loop through the hash for each member and look up their age in the nested hash.
For each member, I want to add a new key/value pair to the existing nested hash called "age_group".
The value of each member's "age_group" will be dependent on their age. For example, if the age is above 65 years I want to have their age_group read "senior", etc.
Problems I'm running into:
I'm confused how I would access just the "age" key_value pair of the nested hash when the first key is different for each member of the family. Meaning, I can't do something like munsters["age"]
because that returns nil (assuming because "age" is nested).
If I had a simple (un-nested) hash it's pretty straightforward. Example of a non-nested hash:
ages = { "Herman" => 32, "Lily" => 30, "Grandpa" => 402, "Eddie" => 10 }
I would then likely loop though like this:
age_group = {}
ages.each do |k, v|
if v >= 65
puts "#{k}'s age of #{v} makes them a senior!"
age_group.merge!("age_group": "senior")
elsif v > 17 && v < 65
puts "#{k}'s age of #{v} makes them an adult"
age_group.merge!("age_group": "adult")
else
puts "#{k}'s age of #{v} makes them a kid."
age_group.merge!("age_group": "kid")
end
end
For the nested hash, I'm able to access the entire nested hash like this:
munsters.each do |k, v|
v.each do |k2, v2|
p "k2 is #{k2} and v2 is #{v2}"
end
end
But that still only returns the entire nested hash to the console instead of just the age:
k2 is age and v2 is 32
k2 is gender and v2 is male
Upvotes: 1
Views: 88
Reputation: 21110
The problem with your current attempt is that you try to do something for each key/value-pair of each munster
. However you are only interested in the "age"
and "age_group"
. So there is no need to iterate the key/value-pairs of munster
. Instead work directly on munster
.
Other examples mostly show mutating solution, so let me offer a non-mutating alternative (meaning that munsters
doesn't change). I've also removed the if-statement to provide an alternative perspective.
threshholds = { "kid" => 0, "adult" => 18, "senior" => 65 }
age_groups = threshholds.each_key.sort_by(&threshholds)
new_munsters = munsters.transform_values do |munster|
age_group = age_groups
.take_while { |age_group| munster["age"] > threshholds[age_group] }
.last
munster.merge("age_group" => age_group)
end
#=> {
# "Herman"=>{"age"=>32, "gender"=>"male", "age_group"=>"adult"},
# "Lily"=>{"age"=>30, "gender"=>"female", "age_group"=>"adult"},
# "Grandpa"=>{"age"=>402, "gender"=>"male", "age_group"=>"senior"},
# "Eddie"=>{"age"=>10, "gender"=>"male", "age_group"=>"kid"},
# "Marilyn"=>{"age"=>23, "gender"=>"female", "age_group"=>"adult"}
# }
This solution uses transform_values
to create a new version of munsters
, containing new updated versions of munster
(created with merge
).
Upvotes: 0
Reputation: 110665
def age_group(age)
case age
when 0..17 then "kid"
when 18..64 then "adult"
else "senior"
end
end
munsters.each_value { |h| h["age_group"] = age_group(h["age"]) }
#=> {"Herman" =>{"age"=>32, "gender"=>"male", "age_group"=>"adult"},
# "Lily" =>{"age"=>30, "gender"=>"female", "age_group"=>"adult"},
# "Grandpa"=>{"age"=>402, "gender"=>"male", "age_group"=>"senior"},
# "Eddie" =>{"age"=>10, "gender"=>"male", "age_group"=>"kid"},
# "Marilyn"=>{"age"=>23, "gender"=>"female", "age_group"=>"adult"}}
This return value is the new value of munsters
.
Upvotes: 1
Reputation: 4440
In addition to @MurifoX answer, you can use #transform_values
ages.transform_values do |value|
if value["age"] >= 65
value["age_group"] = "senior"
elsif value["age"] > 17 && value["age"] < 65
value["age_group"] = "adult"
else
value["age_group"] = "kid"
end
end
Upvotes: 2
Reputation: 15089
The v
is a hash too. So you can do it like this:
ages.each do |k, v|
if v["age"] > 60
ages[k]["age_group"] = "adult"
else
ages[k]["age_group"] = "kid"
end
end
You add a age_group
key with a string value to the k
position of your age hash.
Upvotes: 1