Ruby Adventures

Part 2: Going Loopless

The methods in lib/loopless.rb all work with data about people working on movies. They are all correct, but they all take a loop-based approach to their jobs.

Your task is to convert each of the three methods in this file to use Ruby’s functional-stye list processing instead of loops. (This is a lot like the Java streams you might remember from COMP 127. The two share a common ancestry! This style of programming ends up being quite a bit more convenient in Ruby than it is in Java, and is even more widespread in practice.)

When you are done:

  • There should be no more calls to each.
  • Each method should consist of a single statement, no variable assignments and no list mutations.
  • Each method should have less code than it started with.

You do not need to worry about efficiency for this problem. If you get it working, that is sufficient!

I think these little puzzles benefit from discussion and shared effort.

For part 2 of this homework only, I encourage you to work together with a partner or small group from class if you like. You all still need to commit and push to your own repository, but you can write the code together.

I leave it to you to make a good judgement about how much collaboration helps your own individual learning on this problem, and how much is robbing you of the struggle the creates learning.

If you did work with others, please credit them by Github username (not real names, to protect privacy) in a comment at the top of loopless.rb.

Some of the following Ruby methods might help you:

  • map
  • select
  • include?
  • any?
  • sort_by
  • group_by
  • uniq
  • find_index
  • with_index

You will probably find it helpful to experiment with movie test data using Ruby’s interactive mode:

  • Open a terminal / Powershell / command line in the project directory (cd to it if necessary).

  • Type irb. You should see a prompt something like irb(main):001>. You can type Ruby code here to see what it does.

  • Now copy and paste these two lines into irb:

    require_relative 'test/movie_test_data'
    include MovieTestData
    

    The first line reads the Ruby source code containing movie test data, and the second line includes that test code directly in your irb environment.

    (If the first line fails, you are probably in the wrong directory.)

  • You can now refer to specific pieces of test data directly in irb. Try typing people, movies, maurine, and electric_tears in irb. Look at test/movie_test_data.rb to see all the test data.

  • Experiment with the test data to help you solve the problems. For example, try each of these (one line of code at a time):

    movies.map(&:title)
    movies.map(&:year)
    people.select { |person| person.name.include?("y") }
    deane.roles
    deane.roles.map(&:movie)
    deane.roles.map(&:movie).uniq
    

Once these experiments start to feel comfortable, work on the puzzles in lib/loopless.rb. Remember to run the tests! You will probably want to keep one terminal window open for your irb experiments, and a second window open for running the tests.

Feeling a bit stumped? Here are hints about each specific problem:

Click for a hint about find_all_in_role:

You can do this one with select, map, and include?.

Click for a more specific hint

  1. Figure out how to get the array of roles one specific person has been in.
  2. Figure out how to get the array of names of roles a person has been in.
  3. Figure out how to check whether that contains a specific role name.
  4. Now apply that test to each person, and select the ones who match.

Click for a hint about list_movies:

For this one, read about:

  • map
  • uniq
  • sort_by

Click for a hint about build_credits:

There are several ways to solve this one! Here are methods that could help — and note that while all of them are useful in some possible solution, you will not need all of them in any one particular solution:

  • include?
  • map
  • find_index
  • flat_map
  • select
  • sort_by

Ask me for more hints! The purpose is for you to get the feel of this style of working with collections, not for you to puzzle out every detail of an unfamiliar API all alone.

Remember to run the tests early and often.

When you’re done with this, proceed to part 3.