JumpStart Live Day 6: Exercise

Here’s the final exercise for JSL Day 6.

We need to write a program that does the following:

  • Asks the user to enter the following info about their closest friends:
    • name (not necessarily unique)
    • age
    • favorite color
  • Outputs total number of friends under 18, followed by their names
  • Outputs total number of unique colors, then lists them
  • Should use at least:
    • 1 array
    • 1 hash

My solution includes:

  • a .times loop based on user input
  • an array of hashes
  • two other arrays for printing purposes


Initializing

First, I initialized a) my main array, and b) a method for collecting user input.

JSL-exercise-code1
Initializing an array…and a method for collecting input

The array is created with a simple [] — and then assigned to the variable name friend_data.

My method is called ask, and the argument it accepts is called question.  It prints question, and collects answer with gets.chomp.

(Note:  I used to think I’d need to add return answer…but Ruby automatically does this for us.  Neat!)

Collecting input

Next, I collected and stored input from the user.

JSL-exercise-code2
Code for collecting input about user’s friends

After printing a message to the user, I call my ask method.  The argument is a question asking about the number of friends.

User input is then assigned to variable number_of_friends.

Here’s what that looks like:

JSL-exercise-output1
Asking the user for number of friends

After that, I start a .times loop.  The value inside number_of_friends determines how many times the loop runs.  (Index is represented by i.)

I call my ask method three times — to ask about and collect values for name, age and favorite_color.  (.to_i converts age to an integer, while .downcase converts all answers for favorite_color into lowercase letters.)

Lastly, the .times loop creates a new hash inside the friend_data array.  Each hash represents a single friend (and is assigned to index i inside friend_data).

Key :name is connected to the value inside name, key :age is connected to the value inside age, and key :favorite_color is connected to the value inside favorite_color.

Why did I use an array of hashes?

Hashes are good for storing pairs of information.  An array of hashes means I can use the same keys for each friend — which makes it easier to juggle friends with, say…the same name.

The loop ends when it finishes collecting data for each friend.

Here’s what that looks like:

JSL-exercise-output2
Asking for each friends’ name, age and favorite color

Friends under 18

Next…

  • Calculating and printing number of friends under 18
  • Printing their names
JSL-exercise-code3
Code for 1) calculating number of friends under 18, and 2) printing their names

First, I printed a message that interpolates the number of friends who’re under 18.

Ruby finds this number by:

  • Calling the .count method on friend_data
  • Passing a block that:
    • Iterates over each element in the array (friend)
    • Only counts friend if friend[:age] is under 18

Okay, so now we know how many friends are under 18.  But what about their names?

I wanted to give the printed names an array-like format.  For simplicity’s sake, I decided to use arrays!

First, I initialized a minor_friends array with [].  Then, I iterated over each hash in friend_data with the .each method.

Passing a block, I told Ruby to send friend[:name] into minor_friends — but only if that friend’s age is under 18.

Then, I printed the contents of minor_friends onto a single line (with print).

How?  By:

  • Converting the array to a string (with .to_s)
  • Using gsub to erase each instance of " in the list

Here’s the result:

JSL-exercise-output4
Friends who are under 18!

Number of unique colors

Finally, I needed to:

  • Calculate and print the number of unique favorite colors
  • Print a list of each unique color
JSL-exercise-code4
Code for 1) calculating number of unique colors, and 2) printing the list of colors

Like the original assignment prompt suggested, I turned to the .uniq method.  (Read more about here.)

Wrestling with uniq

The .uniq method returns a new array by removing duplicate values in self.

So, for example,  [1, 1, 2, 2, 3, 3, 4, 4].uniq would return a new array of [1, 2, 3, 4].

However, friend_data.uniq won’t behave quite the same way.  Why?  Because each element is a hash with multiple key-value pairs.

What do I mean?  Well, friend_data.uniq will return an array of hashes…for each friend with a unique color:

JSL-uniq

Combining this syntax with .count tells us how many unique colors we’ve got:

JSL-uniq2

Cool!  (This is how I interpolated the number of unique colors in my array.)

Based on the above, I expected to be able to print out an array of just the colors.  HOWEVER…

JSL-uniq3

You’ll notice blue appears twice.  These aren’t unique colors.

Moreover, this doesn’t even return an array!  AHHHHH.

JSL-uniq4

Pretty frustrating, to say the least!

This is what I ended up doing (for now):

  • Call the .each method on friend_data
  • Pass a block that shovels friend[:favorite_color] into unique_colors
    • …IF friend[:favorite_color] wasn’t already included in unique_colors

How did I figure out if the current color was already included in unique_colors?  With an include? statement!

After that, I used .to_s and gsub to print the array in a pretty list.

Here’s what the output looked like:

JSL-exercise-output5
Unique colors!

Summary

I made a program to collect names, ages and favorite colors of the user’s friends.

I asked the user for a number of friends, and creating a .times loop that runs based on that number.

Then, I collected info for each friend — and stored that information inside an array of hashes.  Each hash represented one friend.

(Arrays of hashes make it easier to store pairs of info, without requiring each friend to have unique keys.)

After that, I created two more arrays to neatly print a) friends who are under 18, and b) unique colors inside of the initial array.

This exercise was a fun way to practice iterating over an array of hashes, and accessing certain values from those hashes.

It was also a cool introduction to the uniq method (which returns a new array without any duplicates).

Leave a comment