Menu
Coddy logo textTech

LINQ for Searching

Part of the Object Oriented Programming section of Coddy's C# journey — lesson 65 of 70.

challenge icon

Challenge

Easy

Let's add powerful search capabilities to your Library System using LINQ! You'll implement methods that let users find books by various criteria - searching by title, filtering by author, and finding available books. LINQ makes these queries elegant and readable.

You'll continue building on your existing project structure:

  • Book.cs: Keep your Book class with Id, Title, Author, and IsAvailable properties, along with the Borrow() and Return() methods.
  • User.cs: Keep your User class with borrowing tracking functionality, including MaxBooks, CanBorrow(), and the methods for managing borrowed books.
  • Library.cs: This is where you'll add your LINQ-powered search methods. In addition to your existing borrowing logic, implement these search capabilities:
    • SearchByTitle(string keyword) - Returns all books where the title contains the keyword (case-insensitive)
    • GetBooksByAuthor(string author) - Returns all books by a specific author (exact match, case-insensitive)
    • GetAvailableBooks() - Returns all books that are currently available
    • GetBorrowedBooks() - Returns all books that are currently borrowed
    Each search method should return a collection of books that can be iterated over.
  • Program.cs: Process search queries and display results.

You will receive the following inputs:

  • Library name
  • Number of books, then each book as id|title|author
  • Number of borrow operations to set up initial state, then each as bookId
  • A search command in one of these formats:
    • title|keyword - search books by title keyword
    • author|name - get books by author
    • available - get all available books
    • borrowed - get all borrowed books

For the search results, print each matching book on its own line in the format {Title} by {Author}. If no books match, print No books found. Results should be printed in the order they appear in the library's collection.

For example, if the inputs are:

City Library
5
B001|The Hobbit|Tolkien
B002|The Lord of the Rings|Tolkien
B003|1984|George Orwell
B004|Animal Farm|George Orwell
B005|The Silmarillion|Tolkien
2
B001
B003
author|Tolkien

The output should be:

The Hobbit by Tolkien
The Lord of the Rings by Tolkien
The Silmarillion by Tolkien

Another example with the same library setup but searching for available books:

City Library
5
B001|The Hobbit|Tolkien
B002|The Lord of the Rings|Tolkien
B003|1984|George Orwell
B004|Animal Farm|George Orwell
B005|The Silmarillion|Tolkien
2
B001
B003
available

The output should be:

The Lord of the Rings by Tolkien
Animal Farm by George Orwell
The Silmarillion by Tolkien

LINQ transforms what would be complex loops into expressive, readable queries. Methods like Where() for filtering and ToList() for materializing results will make your search implementation clean and maintainable!

Try it yourself

using System;
using System.Collections.Generic;

namespace LibrarySystem
{
    class Program
    {
        public static void Main(string[] args)
        {
            // Read library name
            string libraryName = Console.ReadLine();
            
            // Create a Library instance with the library name
            Library library = new Library(libraryName);
            
            // Read number of books
            int numBooks = Convert.ToInt32(Console.ReadLine());
            
            // Read and add books
            for (int i = 0; i < numBooks; i++)
            {
                string bookInput = Console.ReadLine();
                string[] bookParts = bookInput.Split('|');
                string bookId = bookParts[0];
                string bookTitle = bookParts[1];
                string bookAuthor = bookParts[2];
                
                Book book = new Book(bookId, bookTitle, bookAuthor);
                library.AddBook(book);
            }
            
            // Read number of borrow operations to set up initial state
            int numBorrows = Convert.ToInt32(Console.ReadLine());
            
            // Process borrow operations (just book IDs)
            for (int i = 0; i < numBorrows; i++)
            {
                string bookId = Console.ReadLine();
                Book book = library.GetBookById(bookId);
                if (book != null)
                {
                    book.IsAvailable = false;
                }
            }
            
            // Read search command
            string searchCommand = Console.ReadLine();
            
            // Process search command
            List<Book> results = new List<Book>();
            
            if (searchCommand == "available")
            {
                results = library.GetAvailableBooks();
            }
            else if (searchCommand == "borrowed")
            {
                results = library.GetBorrowedBooks();
            }
            else if (searchCommand.Contains("|"))
            {
                string[] parts = searchCommand.Split('|');
                string searchType = parts[0];
                string searchValue = parts[1];
                
                if (searchType == "title")
                {
                    results = library.SearchByTitle(searchValue);
                }
                else if (searchType == "author")
                {
                    results = library.GetBooksByAuthor(searchValue);
                }
            }
            
            // Print results
            if (results.Count == 0)
            {
                Console.WriteLine("No books found");
            }
            else
            {
                foreach (Book book in results)
                {
                    Console.WriteLine($"{book.Title} by {book.Author}");
                }
            }
        }
    }
}

All lessons in Object Oriented Programming