PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question tests a backend engineer's ability to implement correct filtering logic, including case-insensitive substring matching, whitespace trimming, and multi-field search across structured data. It evaluates practical coding skills in applying boolean conditions and edge-case handling, commonly assessed in backend role interviews to gauge real-world API correctness.

  • medium
  • Instacart
  • Coding & Algorithms
  • Backend Engineer

Fix the Broken Search Filter in a Book Catalog API

Company: Instacart

Role: Backend Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Take-home Project

# Fix the Broken Search Filter in a Book Catalog API A small book-management web app lets users search a library catalog. The frontend sends the user's query string to a backend search endpoint, and the backend returns a list of matching books that the page renders. A bug has been reported: **the search results page shows books that do not match the query** — the result list is effectively unfiltered, so typing a specific title or author still returns the entire catalog (or far more than it should). Your job is to implement the backend search function correctly so that it returns **only** the books that match the user's query, according to the rules below. The frontend is not the problem; the defect is in how the backend filters the catalog before returning it. You are given an in-memory catalog of books and must implement a single function that performs the filtering. ## Data model Each book is a record with the following fields: | Field | Type | Description | |------------|-----------------|--------------------------------------------------| | `id` | integer | Unique book id. | | `title` | string | Book title. | | `author` | string | Author's full name. | | `tags` | list of strings | Zero or more lowercase topic tags (may be empty).| | `available`| boolean | Whether the book is currently in stock. | ## Function to implement Implement: ``` search_books(catalog: list[Book], query: str, available_only: bool) -> list[Book] ``` It must return the sublist of `catalog` that satisfies **all** of the matching rules below, **preserving the original order** of `catalog`. ### Matching rules A book matches the query when **any** of the following is a case-insensitive substring match of the trimmed query string `q`: 1. its `title` contains `q`, **or** 2. its `author` contains `q`, **or** 3. at least one of its `tags` contains `q`. Additional rules, applied on top of the substring match: - **Trimming:** leading and trailing whitespace in `query` is ignored. The interior of the query is matched as-is (do not collapse interior spaces). - **Empty query:** if `q` is the empty string after trimming, the query imposes no text filter (every book passes the text condition). - **Case-insensitive:** matching ignores letter case for `title`, `author`, and `tags`. - **Availability filter:** if `available_only` is `true`, only books with `available == true` may be returned; if `false`, availability is ignored. - A book is returned only if it passes **both** the text condition **and** the availability condition. ### Output Return the matching books as a list, in the same relative order they appear in `catalog`. If nothing matches, return an empty list. ## Constraints - `0 <= len(catalog) <= 10^4`. - Each string field has length `<= 200`; each book has `<= 20` tags. - `query` may be empty, may contain leading/trailing whitespace, and may contain mixed case. ## Examples Given the catalog: | id | title | author | tags | available | |----|----------------------|---------------|-----------------------|-----------| | 1 | `Clean Code` | `Robert Martin` | `["programming"]` | `true` | | 2 | `The Pragmatic Programmer` | `Andrew Hunt` | `["programming","craft"]` | `false` | | 3 | `Cooking Basics` | `Jane Cook` | `["food"]` | `true` | - `search_books(catalog, "program", false)` returns books `1` and `2` (both match on `tags`/`title`), in order. - `search_books(catalog, "program", true)` returns only book `1` (book `2` is unavailable). - `search_books(catalog, " COOK ", false)` returns book `3` (matches `author` "Jane **Cook**", case-insensitive, query trimmed). - `search_books(catalog, "", true)` returns books `1` and `3` (empty query passes the text filter; availability filter applied).

Quick Answer: This question tests a backend engineer's ability to implement correct filtering logic, including case-insensitive substring matching, whitespace trimming, and multi-field search across structured data. It evaluates practical coding skills in applying boolean conditions and edge-case handling, commonly assessed in backend role interviews to gauge real-world API correctness.

A book-management web app lets users search a library catalog. The frontend sends the user's query string to a backend search endpoint, and the backend returns matching books. A bug has been reported: the results page shows books that do not match the query — the list is effectively unfiltered. Your job is to implement the backend search function correctly so that it returns ONLY the books that match, according to the rules below. ## Data model Each book is a record with the following fields: | Field | Type | Description | |------------|-----------------|-------------| | `id` | integer | Unique book id. | | `title` | string | Book title. | | `author` | string | Author's full name. | | `tags` | list of strings | Zero or more lowercase topic tags (may be empty). | | `available`| boolean | Whether the book is currently in stock. | In the console, each book is passed as a map/object with keys `id`, `title`, `author`, `tags`, `available`. ## Function to implement ``` searchBooks(catalog, query, available_only) -> list of books ``` Return the sublist of `catalog` that satisfies ALL of the rules below, preserving the original order of `catalog`. ## Matching rules Let `q` be the trimmed query string. A book matches the text condition when ANY of these is a case-insensitive substring match of `q`: 1. its `title` contains `q`, OR 2. its `author` contains `q`, OR 3. at least one of its `tags` contains `q`. Additional rules on top of the substring match: - **Trimming:** leading/trailing whitespace in `query` is ignored. The interior of the query is matched as-is (do not collapse interior spaces). - **Empty query:** if `q` is the empty string after trimming, the query imposes no text filter (every book passes the text condition). - **Case-insensitive:** matching ignores letter case for `title`, `author`, and `tags`. - **Availability filter:** if `available_only` is true, only books with `available == true` may be returned; if false, availability is ignored. - A book is returned only if it passes BOTH the text condition AND the availability condition. Return the matching books in the same relative order they appear in `catalog`. If nothing matches, return an empty list.

Constraints

  • 0 <= len(catalog) <= 10^4
  • Each string field has length <= 200
  • Each book has <= 20 tags
  • query may be empty, may contain leading/trailing whitespace, and may contain mixed case

Examples

Input: ([{"id": 1, "title": "Clean Code", "author": "Robert Martin", "tags": ["programming"], "available": True}, {"id": 2, "title": "The Pragmatic Programmer", "author": "Andrew Hunt", "tags": ["programming", "craft"], "available": False}, {"id": 3, "title": "Cooking Basics", "author": "Jane Cook", "tags": ["food"], "available": True}], "program", False)

Expected Output: [{"id": 1, "title": "Clean Code", "author": "Robert Martin", "tags": ["programming"], "available": True}, {"id": 2, "title": "The Pragmatic Programmer", "author": "Andrew Hunt", "tags": ["programming", "craft"], "available": False}]

Explanation: Book 1 matches on its 'programming' tag; book 2 matches on both its title ('Programmer') and tag. available_only is False so the unavailable book 2 is still returned. Book 3 has no 'program' substring anywhere. Order preserved.

Input: ([{"id": 1, "title": "Clean Code", "author": "Robert Martin", "tags": ["programming"], "available": True}, {"id": 2, "title": "The Pragmatic Programmer", "author": "Andrew Hunt", "tags": ["programming", "craft"], "available": False}, {"id": 3, "title": "Cooking Basics", "author": "Jane Cook", "tags": ["food"], "available": True}], "program", True)

Expected Output: [{"id": 1, "title": "Clean Code", "author": "Robert Martin", "tags": ["programming"], "available": True}]

Explanation: Same query but available_only is True: book 2 matches the text condition but is unavailable, so it is filtered out. Only book 1 remains.

Input: ([{"id": 1, "title": "Clean Code", "author": "Robert Martin", "tags": ["programming"], "available": True}, {"id": 2, "title": "The Pragmatic Programmer", "author": "Andrew Hunt", "tags": ["programming", "craft"], "available": False}, {"id": 3, "title": "Cooking Basics", "author": "Jane Cook", "tags": ["food"], "available": True}], " COOK ", False)

Expected Output: [{"id": 3, "title": "Cooking Basics", "author": "Jane Cook", "tags": ["food"], "available": True}]

Explanation: The query ' COOK ' is trimmed to 'COOK' and lowercased to 'cook'. Book 3 matches on its author 'Jane Cook' (and also its title 'Cooking') case-insensitively. Other books have no 'cook' substring.

Input: ([{"id": 1, "title": "Clean Code", "author": "Robert Martin", "tags": ["programming"], "available": True}, {"id": 2, "title": "The Pragmatic Programmer", "author": "Andrew Hunt", "tags": ["programming", "craft"], "available": False}, {"id": 3, "title": "Cooking Basics", "author": "Jane Cook", "tags": ["food"], "available": True}], "", True)

Expected Output: [{"id": 1, "title": "Clean Code", "author": "Robert Martin", "tags": ["programming"], "available": True}, {"id": 3, "title": "Cooking Basics", "author": "Jane Cook", "tags": ["food"], "available": True}]

Explanation: Empty query imposes no text filter, so every book passes the text condition. available_only is True, so only the available books (1 and 3) are returned; book 2 is unavailable.

Input: ([], "anything", False)

Expected Output: []

Explanation: Empty catalog: there is nothing to filter, so the result is an empty list regardless of query or availability flag.

Input: ([{"id": 5, "title": "Untagged Mystery", "author": "A. Nonymous", "tags": [], "available": True}], "myst", False)

Expected Output: [{"id": 5, "title": "Untagged Mystery", "author": "A. Nonymous", "tags": [], "available": True}]

Explanation: A book with an empty tags list still matches via its title 'Untagged Mystery' (contains 'myst'). The empty tags list must not cause an error.

Input: ([{"id": 7, "title": "Deep Sea", "author": "Marina Blue", "tags": ["Ocean", "NATURE"], "available": True}], "nature", False)

Expected Output: [{"id": 7, "title": "Deep Sea", "author": "Marina Blue", "tags": ["Ocean", "NATURE"], "available": True}]

Explanation: Tag matching is case-insensitive: the stored tag 'NATURE' matches the lowercase query 'nature'. The book is returned even though the match is only on a tag.

Input: ([{"id": 8, "title": "No Match Here", "author": "Someone", "tags": ["misc"], "available": True}], "zzz", False)

Expected Output: []

Explanation: No field (title, author, or any tag) contains the substring 'zzz', so the book fails the text condition and the result is empty.

Hints

  1. Trim and lowercase the query ONCE before the loop. Comparing a pre-lowered query against lowered fields gives case-insensitivity cheaply.
  2. An empty trimmed query must pass the text condition for every book — handle it as a short-circuit so you don't accidentally treat '' as 'matches nothing'.
  3. The availability filter is independent of the text match: a book is returned only if it passes BOTH. Apply the availability check first to skip work.
  4. Preserve input order by iterating the catalog once and appending matches in place — do not sort or re-order.
Last updated: Jun 24, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Find Largest Adjacent Stock Price Change - Instacart (medium)
  • Implement an In-Memory File Storage System - Instacart (medium)
  • Evaluate an arithmetic expression - Instacart (medium)
  • Decode an encoded string - Instacart (medium)
  • Implement worker time and payroll tracker - Instacart (hard)