CodeBlanks Logo Icon CodeBlanks

Search and filter

Write search and filtering with collection methods.

Search and filter

A library may hold thousands of books; to find books by a given author use filter. The line fun searchByAuthor(author: String): List<Book> = books.filter { it.author == author } produces a new list of matching books.

To list available books you filter out the checked-out ones: fun availableBooks(): List<Book> = books.filter { it.isbn !in borrowed }. Here the !in operator checks that the key is absent from the map. This lets you filter non-borrowed books in a single line.

availableBooks and !in

To find non-borrowed books use the !in operator. The expression it.isbn !in borrowed checks that the book number is not a key in the borrowed map.

The method definition: fun availableBooks(): List<Book> = books.filter { it.isbn !in borrowed }. This yields the list of books that are on the shelf. searchByAuthor and availableBooks can be combined: first filter by author, then pick the available ones. Both return new lists, so the original books list is unchanged.

Practice Add searchByAuthor and availableBooks

Add fun searchByAuthor(author: String): List<Book> = books.filter { it.author == author } to the Library class. Also add fun availableBooks(): List<Book> = books.filter { it.isbn !in borrowed }. In main add two Tolstoy books and print them with lib.searchByAuthor("Tolstoy").forEach { println(it) }.

Starter code

Main.kt
data class Book(val title: String, val author: String, val isbn: String)
data class Member(val name: String, val id: String)

class Library {
    val books = mutableListOf<Book>()
    val members = mutableListOf<Member>()
    val borrowed = mutableMapOf<String, String>()

    fun addBook(book: Book) { books.add(book) }
    fun addMember(member: Member) { members.add(member) }
    fun checkout(memberId: String, isbn: String) { borrowed[isbn] = memberId }
    fun returnBook(isbn: String) { borrowed.remove(isbn) }
    // Add searchByAuthor and availableBooks methods
}

fun main() {
    val lib = Library()
    lib.addBook(Book("War and Peace", "Tolstoy", "978-1"))
    lib.addBook(Book("Anna Karenina", "Tolstoy", "978-2"))
    // searchByAuthor call: author Tolstoy
}

Sample solution

Main.kt
data class Book(val title: String, val author: String, val isbn: String)
data class Member(val name: String, val id: String)

class Library {
    val books = mutableListOf<Book>()
    val members = mutableListOf<Member>()
    val borrowed = mutableMapOf<String, String>()
    fun addBook(book: Book) { books.add(book) }
    fun addMember(member: Member) { members.add(member) }
    fun checkout(memberId: String, isbn: String) { borrowed[isbn] = memberId }
    fun returnBook(isbn: String) { borrowed.remove(isbn) }
    fun searchByAuthor(author: String): List<Book> = books.filter { it.author == author }
    fun availableBooks(): List<Book> = books.filter { it.isbn !in borrowed }
}

fun main() {
    val lib = Library()
    lib.addBook(Book("War and Peace", "Tolstoy", "978-1"))
    lib.addBook(Book("Anna Karenina", "Tolstoy", "978-2"))
    lib.searchByAuthor("Tolstoy").forEach { println(it) }
}

Expected output

Book(title=War and Peace, author=Tolstoy, isbn=978-1)
Book(title=Anna Karenina, author=Tolstoy, isbn=978-2)

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What does books.filter { it.author == author } return?

  • The list of all books
  • The list of books whose author matches Correct answer
  • A single book
  • An empty list

Explanation: filter builds a new list of elements that satisfy the condition.

2 Complete the filter call

Question
books.____ { it.author == author }
Answer
books.filter { it.author == author }

Explanation: filter selects elements matching the condition.

3 Match the filter expressions

Term Meaning
filter { it.author == a } Search by author
filter { it.isbn !in b } Available books
forEach { println(it) } Print
mutableListOf<Book>() Create list

All lessons in Intermediate