如何在嵌套的Ruby哈希上进行迭代,以基于现有的键/值数据添加新的键/价值对


  1. 我有一个嵌套的数据哈希:

    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"}
    }
    
  2. 我想循环遍历每个成员的哈希,并在嵌套哈希中查找他们的年龄。

  3. 对于每个成员,我想在现有的嵌套散列中添加一个新的键值对,称为"age_group"。

  4. 每个成员的"年龄组"的值将取决于他们的年龄。例如,如果年龄在65岁以上,我想让他们的年龄组读成"老年人"等。

我遇到的问题:

当族中每个成员的第一个键不同时,我很困惑如何只访问嵌套哈希的"age"key_value对。也就是说,我不能做像munsters["age"]这样的事情,因为它返回nil(假设因为嵌套了"age"(。

如果我有一个简单的(非嵌套的(散列,它是非常简单的。非嵌套散列示例:

ages = { "Herman" => 32, "Lily" => 30, "Grandpa" => 402, "Eddie" => 10 }

然后我可能会这样循环:

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

对于嵌套哈希,我可以访问整个嵌套哈希,如下所示:

munsters.each do |k, v|
v.each do |k2, v2|
p "k2 is #{k2} and v2 is #{v2}"
end
end

但这仍然只会将整个嵌套哈希返回到控制台,而不仅仅是年龄:

k2 is age and v2 is 32
k2 is gender and v2 is male

除了@MurifoX答案,您还可以使用#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

v也是一个散列。所以你可以这样做:

ages.each do |k, v|
if v["age"] > 60
ages[k]["age_group"] = "adult"
else
ages[k]["age_group"] = "kid"
end
end

将一个带有字符串值的age_group密钥添加到年龄哈希的k位置。

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"}}

此返回值是munsters的新值。

当前尝试的问题是,您试图为每个munster的每个键/值对做一些事情。但是,您只对"age""age_group"感兴趣。因此,不需要对munster的键/值对进行迭代。相反,直接在munster上工作。

其他例子大多显示了突变的解决方案,所以让我提供一个非突变的替代方案(意味着munsters不会改变(。我还删除了if-语句,以提供另一种视角。

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"}
# }

此解决方案使用transform_values创建munsters的新版本,其中包含munster的新更新版本(使用merge创建(。

最新更新