Reputation: 11
I am trying to process a series of sports results that get supplied as a text file. Each line contains the name of the home team, the name of the away team, and the result. I need to then update a league table to show a number of stats for each team.
I was initially trying it as a class but think it might be simpler as a nested hash, as I don't think I can set new objects without knowing the team names, and this could change later, for example if I get data in for a new team playing I think it's easier to add it to a hash as this would hopefully be a unique name.
None of the answers I have found here seem to fix my issue. Is this because I am going about it the wrong way?
example input:
``file =<<~MSG
Team A, Team B, win
Team C, Team A, draw
Team C, Team B, lose
...
MSG``
so I read each line:
``file.each_line do |score_line|
match_info = score_line.delete!("\n").split(';') # [<home>,<away>,<score>]
home = match_info[0]
away = match_info[1]
score = match_info[2]
...
end``
I now have each team and the score to play with. This is where I am stumped. I am trying to create a nested hash the first level being the team name the next level being the stats.
For example:
``=> { 'Team A' => {:matches_played=> 2, :wins=> 1, :draw=> 1, lose=> 0},
'Team B' => {:matches-played=> 2, :wins=> 1, :draw=> 0, lose=> 1},
...``
If I create a simple hash of one level, (e.g. Team => matches played) I have no trouble updating the hashes. For some reason as soon as I try to update the second level I get problems.
As the info is coming in I need to update the team stats, this could be as the home or away team, so I am using the variables home
and away
from the above example. To avoid re-setting the initial values of the hash, I have tried using #unless
which just returns an empty hash.
For example:
`` unless table.has_key?(home)
table[home] = {:matches_played=> 1, :wins=> 0, :draw=> 0, lose=> 0}
end
unless table.has_key?(away)
table[away] = {:matches_played=> 1, :wins=> 0, :draw=> 0, lose=> 0}
end``
the idea was to then update the values of the keys in the second level depending on the score
.
Currently I can't even get the second hash implemented, although the programme runs without errors, when I print out the hash I get => {}
. Without the #unless
the hash just keeps getting the initial values reset with each line read.
I am new to Ruby but feel that I will always need to create/access nested hashes outside of a database so trying to learn.
Upvotes: 1
Views: 28
Reputation: 114188
Assuming that after processing your file / input, you have an array like this:
results = [
["Team A", "Team B", "win"],
["Team C", "Team A", "draw"],
["Team C", "Team B", "lose"]
]
You could create a hash using a default proc which sets the defaults for a new entry:
table = Hash.new { |h, k| h[k] = { matches_played: 0, wins: 0, draw: 0, lose: 0 } }
Now, you can process the above results in a loop like this:
results.each do |home, away, score|
table[home][:matches_played] += 1
table[away][:matches_played] += 1
case score
when 'win'
table[home][:wins] += 1
table[away][:lose] += 1
when 'lose'
table[home][:lose] += 1
table[away][:wins] += 1
when 'draw'
table[home][:draw] += 1
table[away][:draw] += 1
end
end
The default proc ensures that each sub-hash is present with values initially set to 0.
Instead of a default proc, you could also conditionally assign each initial hash explicitly:
results.each do |home, away, score|
table[home] ||= { matches_played: 0, wins: 0, draw: 0, lose: 0 }
table[away] ||= { matches_played: 0, wins: 0, draw: 0, lose: 0 }
# ...
end
Either of the above results in the following table
:
{
"Team A"=>{:matches_played=>2, :wins=>1, :draw=>1, :lose=>0},
"Team B"=>{:matches_played=>2, :wins=>1, :draw=>0, :lose=>1},
"Team C"=>{:matches_played=>2, :wins=>0, :draw=>1, :lose=>1}
}
Upvotes: 0