Lab: Enumeration and LINQ

In this lab, we're going to make a data source for books, recall how to use binary trees, and practice setting up enumeration with yield return. And, for the heck of it, we'll do a hands-on LINQ query.

Since this is a console application, you will only need to commit the Program.cs file. The repo is here:

https://cssvn.utrgv.edu/svn_etomai/201810_3328/lab09_enumerate/<username>

Killin' Trees

Trees are great! They're very useful, and simple once you get used to them. First though, we need some data to store, so we're going to create a Book class. Using properties, make your Book class able to store:

  • Title
  • Author last name
  • Author first name
  • Year of publication

Give it a parameterized constructor and override ToString, for convenience.

I think that I shall never see...

A binary tree is the next step up from a linked list. It has nodes and root pointer just the same, but instead of one next node, it has two child nodes. Often called left and right. Create a Node class that hold (using properties!):

  • A left Node reference (remember that all class variables in C# work like pointers)
  • A right Node reference
  • A Book object as data

Parameterized constructor, ToString, of course.

How Does Your Garden Grow?

Recursive methods are really nice on trees. For example, we want a method that adds a new Book to a tree. This breaks down easily into:

  • If you have an empty left or right, create a new node there for this Book.
  • Otherwise, ask your left tree to add the book.

Likewise, printing with a in-order traversal breaks down into:

  • Ask your left tree to print itself
  • Print your Book
  • Ask your right tree to print itself

Create a root node for a Book, add six more Books to that tree, and print it. Why does it print in the order that it does?

Forest for the Trees

Above, we did a traversal and printed out the nodes. Now let's look at how to iterate over the nodes (in in-order order) using IEnumerable<> and yield return.

I want to be able to do this with my tree (the property names don't have to match):

foreach (Book b in root.GetBooks()) {
  if (b.YearPublished > 1990) {
    Console.WriteLine("({0}) {1}", b.YearPublished, b.Title);
  }
}

You could, of course, create a new recursive traversal method in Node to filter by year, and alter ToString to get the output format I want, but the point is that I want to be able to loop over the nodes in the tree in in-order order.

We saw last class that we can use yield return to have a method return items one-by-one as an IEnumerable (which can be looped over with foreach). Here's a trivial example:

public IEnumerable<int> Values()
{
  yield return 1;
  yield return 2;
  yield return 3;
}

Create a new recusive traversal method, just like your printing method above, but instead of printing each Book, use yield return to return them one-by-one. Just like in print, this breaks down to:

  • Return each Book from your left tree
  • Return your Book
  • Return each Book from your right tree

LINQ Something About Trees

Finally, replace the foreach loop above with a LINQ query that prints only the books published after 1990, sorted by the author's last name! The LINQ docs and examples are on the calendar from last class.

Don't forget to commit by the end of today for lab credit.