- Practice building nested hashes
This and the next lab are about as representative of real-life tasks as a programmer as you can get: data on paper or in tables needs to be given to a programming language to deliver insights.
Your task is to perform an analysis on an NBA game. You've been provided some basic game data in a series of tables. Your goal is use Ruby to help you answer some questions about the game, but before we can work with the data, we need to put it in a useful format.
This challenge comes in two major pieces:
- Build a nested data structure from text and data stored in tables
- Process the nested data structure to produce insights about how various players performed
While you've worked with nested data structures using simple looping and Enumerables, you've never before had to create such a complex nested data structure and process it as well. We've split this challenge into two labs so you can just focus on the first task here - building the NDS.
Code your solution in hashketball.rb
following the steps below. Because this
lab is so big, we'll show you new techniques for running only small chunks of
the test suite so that you're not overwhelmed by all the test data!
There is one method in this lab to implement: game_hash
. This method contains and
returns a hash nested in the following manner:
- The top level of the hash has two keys:
:home
, for the home team, and:away
, for the away team. - The values of the
:home
and:away
keys are hashes. These hashes have the following keys::team_name
:colors
:players
- The
:team_name
key points to a string of the team name. - The
:colors
key points to an array of strings that are that team's colors. - The
:players
key points to anArray
ofHash
es. EachHash
in theArray
should contain the players' stats. Each stat should be a key that points to a value for that stat. The keys should be::player_name
:number
:shoe
:points
:rebounds
:assists
:steals
:blocks
:slam_dunks
- The data for each player is provided in a table below.
Home Team:
- team name: Brooklyn Nets
- colors: Black, White
- players:
Stat | Info | Info | Info | Info | Info |
---|---|---|---|---|---|
Player Name | Alan Anderson | Reggie Evans | Brook Lopez | Mason Plumlee | Jason Terry |
Number | 0 | 30 | 11 | 1 | 31 |
Shoe | 16 | 14 | 17 | 19 | 15 |
Points | 22 | 12 | 17 | 26 | 19 |
Rebounds | 12 | 12 | 19 | 11 | 2 |
Assists | 12 | 12 | 10 | 6 | 2 |
Steals | 3 | 12 | 3 | 3 | 4 |
Blocks | 1 | 12 | 1 | 8 | 11 |
Slam Dunks | 1 | 7 | 15 | 5 | 1 |
Away Team:
- team name: Charlotte Hornets
- colors: Turquoise, Purple
- players:
Stat | Info | Info | Info | Info | Info |
---|---|---|---|---|---|
Player Name | Jeff Adrien | Bismack Biyombo | DeSagna Diop | Ben Gordon | Kemba Walker |
Number | 4 | 0 | 2 | 8 | 33 |
Shoe | 18 | 16 | 14 | 15 | 15 |
Points | 10 | 12 | 24 | 33 | 6 |
Rebounds | 1 | 4 | 12 | 3 | 12 |
Assists | 1 | 7 | 12 | 2 | 12 |
Steals | 2 | 22 | 4 | 1 | 7 |
Blocks | 7 | 15 | 5 | 1 | 5 |
Slam Dunks | 2 | 10 | 5 | 0 | 12 |
Write a method called game_hash
that returns your nested data structure. We
might suggest starting with having game_hash
return only a {}
. Then run the
game_hash
tests (see next section) and slowly build up your nested data
structure to satisfy those tests. We'll describe the strategy here in the next
sections.
Writing nested data structures is challenging because we humans can lose track
of whether or not we closed a {...}
set or added a ,
in the right place.
Running a small chunk of tests (more on that in the next section ) to make sure
our nested data structure is syntactically valid (i.e. honors Ruby's grammar
rules) is a good idea. This allows a process like:
- Start with something syntactically valid, but incorrect e.g.
{}
- Make an edit
- run the tests
- Is the nested data structure valid? Great!
- Make another edit
- Run the tests...error!
- Add missing comma
- Add the comma
- Run tests...
- Working again!
Syntactically valid, but incorrect nested data structures are easier to correct than to fix syntactically invalid and incorrect nested data structures. Constantly asking Ruby "Hey can you read this?" means that you're never have a mountain of things that are broken...maybe small, more-easily-fixed little pile.
Once you have a syntactically valid, but incorrect nested data structure, you can slowly add to the nested data structure and move it to being correct. A key strategy to iterating towards correctness is running a small subset of tests to have Ruby validate our nested data structure instead of our error-prone human eyes.
When we have a lot of tests and run them all with learn
and get back all
those failing messages it can make us feel sad. It's like telling someone
you're trying to learn an étude on piano and they keep telling you it's not
perfect yet. "Yeah, we know, that's why we said we're l-e-a-r-n-i-n-g it."
We can run a specific test by running RSpec on the spec file, then adding a colon and the line number where the test is located in the file. The following, for example, will run first test in the lab only:
rspec spec/hashketball_spec.rb:50
But changing the line to 54
will run the second test only:
rspec spec/hashketball_spec.rb:54
The remaining three tests in this lab are on lines 60
, 66
, and 82
.
Alternative, if you want to run a section of tests, you can do so using the
following command from the CLI:
rspec spec/hashketball_spec.rb -e game_hash
The thing that lets us run only a portion of the test suite is the -e
for
--example
flag. It means "only run tests in a section that matches the word
game_hash
." You can read more about it in the RSpec documentation for --example
.
In this example, since we only have one section of tests, this command outputs
the same results as running learn
.
The learn
program uses rspec
to evaluate test success. So, if we get a
subset of the tests working, as proved by rspec
, we can trust that those tests
will pass when we run learn
.
Wisdom: Move from working to working to working. Never let "broken in this way, and that way, and that way" mount up!
With the data structured into a nested data structure, we can move on to working with the data and drawing out information.
Work where you processed Array
of Arrays
or Array
s of Hash
es would be
wise to freshen up on as preparation for the next lab. Take it in pieces,
remember your training, and you'll get there!
We also strongly recommend that you read the entire README before you start coding. We're going to show some tips and tricks that make the coding a lot easier...but only if you read through to the end.