Reputation: 117
My goal is to take a hash of names and numbers, for example:
hash = {
"Matt" => 30,
"Dave" => 50,
"Alex" => 60
}
and to group them by whether they achieved a "passing" score. I'd like the results to be passed as an array into two separate keys, say :pass
and :fail
like this:
hash = { "pass" => ["Alex", 60], "fail" => [["Matt", 30]["Dave",60]]}
I know the group_by
method is what I need, but am not sure as to how I would pass the values into the new keys.
The passing grade should be decided by the user. For this example, you could use 45.
Upvotes: 1
Views: 1331
Reputation: 110685
Here are two ways:
#1
a = hash.to_a
{ "pass" => a.select { |_,v| v > 50 }, "fail" => a.reject { |_,v| v > 50 } }
#=> {"pass"=>[["Alex", 60]], "fail"=>[["Matt", 30], ["Dave", 50]]}
#2
[:pass, :fail].zip(hash.to_a.partition { |_,v| v > 50 }).to_h
#=> {:pass=>[["Alex", 60]], :fail=>[["Matt", 30], ["Dave", 50]]}
These both give the return values as arrays of tuples, which you wanted for "fail"
but not for "pass"
. Wouldn't that make it a pain to work with? Is it not better for both to be arrays of tuples?
Consider returning hashes for values:
{"pass" => hash.select { |_,v| v > 50 }, "fail" => hash.reject {|_,v| v > 50 }}
#=> {"pass"=>{"Alex"=>60}, "fail"=>{"Matt"=>30, "Dave"=>50}}
Would that not be more convenient?
Upvotes: 0
Reputation: 1574
You can do somthing this in such way:
PASSING_GRADE = 45
hash.group_by {|_, v| v >= PASSING_GRADE ? 'pass' : 'fail'}
Here is result:
{"fail"=>[["Matt", 30], "pass"=>[["Alex", 60], ["Dave", 50]]]}
Upvotes: 6
Reputation: 727
You could simply do something like this:
sorted = {"pass" => [], "fail" => []}
hash.each do |name, grade|
if grade >= PASSING_GRADE
sorted["pass"] << [name, grade]
else
sorted["fail"] << [name, grade]
end
end
Upvotes: 1