Task Manager: Filter, Deduplicate, Multi-Key Sort, Then Order Subtasks Around Parents

Read the full interview experience this question came from →

Quick Overview

Implement a task manager class that keeps open, unassigned tasks, drops duplicates by description and deadline, and prints them ordered by deadline, priority and creation time. A follow-up part orders multi-level subtasks before or after their parents, testing multi-key sorting, tree traversal and requirement clarification.

Task Manager: Filter, Deduplicate, Multi-Key Sort, Then Order Subtasks Around Parents

Company: Meta

Role: Data Engineer

Category: Software Engineering Fundamentals

Difficulty: hard

Interview Round: Technical Screen

Implement a `TaskManager` class. Its constructor receives a list of existing tasks, and its method `print_prioritized_tasks()` prints the tasks that pass a filter, with duplicates removed, in a prescribed order. Once the base version works, the interviewer extends it to tasks nested under parent tasks at several levels. The exercise is light on algorithms; it tests clarifying the requirements, choosing data structures, multi-key sorting and walking a tree. Every task has eight fields. The report lists the fields but not their names or exact types, so the names below are illustrative: | Field | Type | Meaning | | --- | --- | --- | | `id` | int | Task id | | `description` | str | What the task is | | `is_completed` | bool | Whether the task is done | | `due_date` | str or None | Deadline, or none | | `parent_id` | int or None | Id of the parent task, or none | | `assignee` | str or None | Who owns the task, or none when unassigned | | `is_high_priority` | bool | Whether the task is high priority | | `created_at` | int | Creation timestamp | ### Constraints and Clarifications The interviewer confirmed these points: - Task ids are unique, and every deadline is a string in `YYYY-MM-DD` format. - Every `parent_id` that is present refers to a task in the input list, so a parent's description can always be looked up, even when the parent itself is not printed. - When several tasks share a deduplication key, the first one that passes the filter is kept. - Tasks without a deadline always come after every task that has one. - Output goes to the console with `print()`, one line per task. Assume also: - "First" means first in the input list. - A missing deadline is part of the deduplication key, so two undated tasks with the same description are duplicates. Two missing deadlines also count as equal for ordering, so the priority and creation-time rules order the undated tasks among themselves. - The report names the pieces of each output line but not their punctuation. Use `Task ID: <id>, Description: <description>`, and append `, parent: <parent description>` when the task has a parent. ### Clarifying Questions - Does "unassigned" mean only a missing assignee, or does an empty string count as unassigned too? - Can two tasks share a creation timestamp, and if so, which one prints first? - Should the method only print, or also return the lines so the order can be tested? ### Part 1 — Filter, deduplicate and sort Implement the constructor and `print_prioritized_tasks()` with these rules. Filtering and deduplication: - Keep only tasks that are not completed and have no assignee. - The deduplication key is the task's description together with its deadline. - Among tasks with the same key, keep only the first one that passes the filter. Ordering: - Tasks with a deadline come first, in ascending deadline order. - For equal deadlines, high-priority tasks come before the others. - For equal priority, the task created earlier comes first. - Tasks without a deadline come after all tasks with a deadline. Example input, in this order (a dash means the field is empty): | id | description | completed | due date | parent | assignee | high priority | created | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 | Plan conference | no | 2030-05-20 | — | — | no | 1 | | 2 | Book keynote speaker | no | 2030-05-01 | 1 | — | no | 2 | | 3 | Print badges | no | 2030-05-25 | 1 | — | yes | 3 | | 4 | Order lanyards | no | 2030-05-22 | 3 | — | no | 4 | | 5 | Draft speaker brief | no | — | 2 | — | no | 5 | | 6 | Clean up shared drive | no | — | — | — | no | 6 | | 7 | Rename folders | no | 2030-05-20 | 6 | — | yes | 7 | | 8 | Write retrospective | no | — | 1 | — | yes | 8 | | 9 | Order catering | yes | 2030-05-10 | 1 | — | no | 9 | | 10 | Book keynote speaker | no | 2030-05-01 | 1 | — | yes | 10 | | 11 | Reserve venue | no | 2030-05-02 | — | user_42 | yes | 11 | Expected output: ```text Task ID: 2, Description: Book keynote speaker, parent: Plan conference Task ID: 7, Description: Rename folders, parent: Clean up shared drive Task ID: 1, Description: Plan conference Task ID: 4, Description: Order lanyards, parent: Print badges Task ID: 3, Description: Print badges, parent: Plan conference Task ID: 8, Description: Write retrospective, parent: Plan conference Task ID: 5, Description: Draft speaker brief, parent: Book keynote speaker Task ID: 6, Description: Clean up shared drive ``` Task 9 (completed) and task 11 (assigned) are filtered out. Task 10 has the same description and deadline as task 2, which comes first, so task 10 is dropped even though it is high priority. Tasks 7 and 1 share a deadline, and task 7 is high priority. Among the tasks without a deadline, task 8 is high priority, and task 5 was created before task 6. ```hint Order of importance Write the four ordering rules from most to least important, then check how a missing deadline and a true/false priority flag behave under a plain ascending sort. ``` #### What This Part Should Cover - The filter, the deduplication key and the first-qualifying-record rule, applied in the right order - An ordering that encodes all four rules, including missing deadlines and the priority flag - Line formatting with the parent's description looked up among all tasks, and the time and space cost ### Part 2 — Multi-level subtasks Tasks can now nest to any depth through `parent_id`. Extend `print_prioritized_tasks()` so the output also respects the hierarchy: - A child task normally follows right after its parent. - A child comes before its parent if the child has a deadline and the parent does not, or if the child's deadline is earlier than the parent's. - Children of the same parent keep the Part 1 order among themselves. - The same rules apply recursively at every deeper level. Filtering, deduplication and the line format stay as in Part 1. Assume that top-level tasks keep the Part 1 order, and that a child placed ahead of its parent takes its own ordered subtree with it. While you outline the approach, the interviewer checks your plan: you would keep a global structure holding every task and, when you are about to print a task, look at its children first. Explain which data structures you keep and how you make sure no task is printed twice. In the example above, every qualifying task's parent also qualifies, and the expected output becomes: ```text Task ID: 2, Description: Book keynote speaker, parent: Plan conference Task ID: 5, Description: Draft speaker brief, parent: Book keynote speaker Task ID: 1, Description: Plan conference Task ID: 4, Description: Order lanyards, parent: Print badges Task ID: 3, Description: Print badges, parent: Plan conference Task ID: 8, Description: Write retrospective, parent: Plan conference Task ID: 7, Description: Rename folders, parent: Clean up shared drive Task ID: 6, Description: Clean up shared drive ``` Task 1's children in Part 1 order are 2, 3 and 8. Task 2 is due before task 1, so task 2 and its subtree (task 5, which has no deadline and therefore follows task 2) print before task 1. Task 3 is due later and task 8 has no deadline, so both follow task 1; inside task 3's subtree, task 4 is due before task 3 and prints first. Task 7 has a deadline and its parent, task 6, has none, so task 7 prints before task 6. The top-level tasks 1 and 6 keep the Part 1 order. ```hint One parent at a time Look at a single parent with its children already in Part 1 order, decide which of them must print before the parent, and then ask what that means for each child's own children. ``` #### Clarifying Questions for this Part - A task qualifies, but its parent is completed, assigned or dropped as a duplicate. Does the task become a top-level task, and does its line still carry the parent suffix? - Does the hierarchical order replace the Part 1 order in `print_prioritized_tasks()`, or should both orders stay available? #### What This Part Should Cover - The data structures: a lookup by id, a list of children per parent in Part 1 order, and a record of tasks already printed - The split of each parent's children into those printed before it and those printed after it, and the recursion that carries whole subtrees - A stated policy for qualifying tasks whose parent does not qualify, and the cost of the traversal ### What a Strong Answer Covers - Clarifying questions that each map to a branch or an assumption in the code: which duplicate survives, where missing deadlines go, whether parents can be missing, where output goes, unique ids and the date format - Filtering before deduplicating, keeping the first qualifying record in input order, and looking parents up among all tasks rather than only the printed ones - One ordering definition shared by the global sort and the sibling order, so the extension reuses Part 1 instead of rewriting it - A Part 2 traversal that prints every qualifying task exactly once and states its choice where the rules leave a gap - Complexity for both parts, and robustness to malformed parent links and very deep hierarchies - A clean class split between construction, filtering, ordering and printing ### Follow-up Questions - The data contains a cycle: task A is task B's parent and task B is task A's parent. What does your Part 2 code do, and how should it detect and report the problem? - The hierarchy is many thousands of levels deep. What fails, and how do you rewrite the traversal? - A grandchild is due earlier than its grandparent, but its parent is due later than the grandparent or has no deadline. Where does your code print the grandchild, and what would change if every task had to print before all ancestors due later than it? - Tasks are added, completed and reassigned after construction, and the method is called often. What would you maintain incrementally instead of recomputing on every call?

Overview: Implement a task manager class that keeps open, unassigned tasks, drops duplicates by description and deadline, and prints them ordered by deadline, priority and creation time. A follow-up part orders multi-level subtasks before or after their parents, testing multi-key sorting, tree traversal and requirement clarification.

Read the full Meta Data Engineer interview experience this question came from

Meta logo
Meta
Nov 7, 2026
hardData EngineerTechnical ScreenSoftware Engineering Fundamentals
1
0

Implement a TaskManager class. Its constructor receives a list of existing tasks, and its method print_prioritized_tasks() prints the tasks that pass a filter, with duplicates removed, in a prescribed order. Once the base version works, the interviewer extends it to tasks nested under parent tasks at several levels. The exercise is light on algorithms; it tests clarifying the requirements, choosing data structures, multi-key sorting and walking a tree.

Every task has eight fields. The report lists the fields but not their names or exact types, so the names below are illustrative:

FieldTypeMeaning
idintTask id
descriptionstrWhat the task is
is_completedboolWhether the task is done
due_datestr or NoneDeadline, or none
parent_idint or NoneId of the parent task, or none
assigneestr or NoneWho owns the task, or none when unassigned
is_high_priorityboolWhether the task is high priority
created_atintCreation timestamp

Constraints and Clarifications

The interviewer confirmed these points:

  • Task ids are unique, and every deadline is a string in YYYY-MM-DD format.
  • Every parent_id that is present refers to a task in the input list, so a parent's description can always be looked up, even when the parent itself is not printed.
  • When several tasks share a deduplication key, the first one that passes the filter is kept.
  • Tasks without a deadline always come after every task that has one.
  • Output goes to the console with print() , one line per task.

Assume also:

  • "First" means first in the input list.
  • A missing deadline is part of the deduplication key, so two undated tasks with the same description are duplicates. Two missing deadlines also count as equal for ordering, so the priority and creation-time rules order the undated tasks among themselves.
  • The report names the pieces of each output line but not their punctuation. Use Task ID: <id>, Description: <description> , and append , parent: <parent description> when the task has a parent.

Clarifying Questions Guidance

  • Does "unassigned" mean only a missing assignee, or does an empty string count as unassigned too?
  • Can two tasks share a creation timestamp, and if so, which one prints first?
  • Should the method only print, or also return the lines so the order can be tested?

Part 1 — Filter, deduplicate and sort

Implement the constructor and print_prioritized_tasks() with these rules.

Filtering and deduplication:

  • Keep only tasks that are not completed and have no assignee.
  • The deduplication key is the task's description together with its deadline.
  • Among tasks with the same key, keep only the first one that passes the filter.

Ordering:

  • Tasks with a deadline come first, in ascending deadline order.
  • For equal deadlines, high-priority tasks come before the others.
  • For equal priority, the task created earlier comes first.
  • Tasks without a deadline come after all tasks with a deadline.

Example input, in this order (a dash means the field is empty):

iddescriptioncompleteddue dateparentassigneehigh prioritycreated
1Plan conferenceno2030-05-20——no1
2Book keynote speakerno2030-05-011—no2
3Print badgesno2030-05-251—yes3
4Order lanyardsno2030-05-223—no4
5Draft speaker briefno—2—no5
6Clean up shared driveno———no6
7Rename foldersno2030-05-206—yes7
8Write retrospectiveno—1—yes8
9Order cateringyes2030-05-101—no9
10Book keynote speakerno2030-05-011—yes10
11Reserve venueno2030-05-02—user_42yes11

Expected output:

Task ID: 2, Description: Book keynote speaker, parent: Plan conference
Task ID: 7, Description: Rename folders, parent: Clean up shared drive
Task ID: 1, Description: Plan conference
Task ID: 4, Description: Order lanyards, parent: Print badges
Task ID: 3, Description: Print badges, parent: Plan conference
Task ID: 8, Description: Write retrospective, parent: Plan conference
Task ID: 5, Description: Draft speaker brief, parent: Book keynote speaker
Task ID: 6, Description: Clean up shared drive

Task 9 (completed) and task 11 (assigned) are filtered out. Task 10 has the same description and deadline as task 2, which comes first, so task 10 is dropped even though it is high priority. Tasks 7 and 1 share a deadline, and task 7 is high priority. Among the tasks without a deadline, task 8 is high priority, and task 5 was created before task 6.

What This Part Should Cover Guidance

  • The filter, the deduplication key and the first-qualifying-record rule, applied in the right order
  • An ordering that encodes all four rules, including missing deadlines and the priority flag
  • Line formatting with the parent's description looked up among all tasks, and the time and space cost

Part 2 — Multi-level subtasks

Tasks can now nest to any depth through parent_id. Extend print_prioritized_tasks() so the output also respects the hierarchy:

  • A child task normally follows right after its parent.
  • A child comes before its parent if the child has a deadline and the parent does not, or if the child's deadline is earlier than the parent's.
  • Children of the same parent keep the Part 1 order among themselves.
  • The same rules apply recursively at every deeper level.

Filtering, deduplication and the line format stay as in Part 1. Assume that top-level tasks keep the Part 1 order, and that a child placed ahead of its parent takes its own ordered subtree with it.

While you outline the approach, the interviewer checks your plan: you would keep a global structure holding every task and, when you are about to print a task, look at its children first. Explain which data structures you keep and how you make sure no task is printed twice.

In the example above, every qualifying task's parent also qualifies, and the expected output becomes:

Task ID: 2, Description: Book keynote speaker, parent: Plan conference
Task ID: 5, Description: Draft speaker brief, parent: Book keynote speaker
Task ID: 1, Description: Plan conference
Task ID: 4, Description: Order lanyards, parent: Print badges
Task ID: 3, Description: Print badges, parent: Plan conference
Task ID: 8, Description: Write retrospective, parent: Plan conference
Task ID: 7, Description: Rename folders, parent: Clean up shared drive
Task ID: 6, Description: Clean up shared drive

Task 1's children in Part 1 order are 2, 3 and 8. Task 2 is due before task 1, so task 2 and its subtree (task 5, which has no deadline and therefore follows task 2) print before task 1. Task 3 is due later and task 8 has no deadline, so both follow task 1; inside task 3's subtree, task 4 is due before task 3 and prints first. Task 7 has a deadline and its parent, task 6, has none, so task 7 prints before task 6. The top-level tasks 1 and 6 keep the Part 1 order.

Clarifying Questions for this Part Guidance

  • A task qualifies, but its parent is completed, assigned or dropped as a duplicate. Does the task become a top-level task, and does its line still carry the parent suffix?
  • Does the hierarchical order replace the Part 1 order in print_prioritized_tasks() , or should both orders stay available?

What This Part Should Cover Guidance

  • The data structures: a lookup by id, a list of children per parent in Part 1 order, and a record of tasks already printed
  • The split of each parent's children into those printed before it and those printed after it, and the recursion that carries whole subtrees
  • A stated policy for qualifying tasks whose parent does not qualify, and the cost of the traversal

What a Strong Answer Covers Guidance

  • Clarifying questions that each map to a branch or an assumption in the code: which duplicate survives, where missing deadlines go, whether parents can be missing, where output goes, unique ids and the date format
  • Filtering before deduplicating, keeping the first qualifying record in input order, and looking parents up among all tasks rather than only the printed ones
  • One ordering definition shared by the global sort and the sibling order, so the extension reuses Part 1 instead of rewriting it
  • A Part 2 traversal that prints every qualifying task exactly once and states its choice where the rules leave a gap
  • Complexity for both parts, and robustness to malformed parent links and very deep hierarchies
  • A clean class split between construction, filtering, ordering and printing

Follow-up Questions Guidance

  • The data contains a cycle: task A is task B's parent and task B is task A's parent. What does your Part 2 code do, and how should it detect and report the problem?
  • The hierarchy is many thousands of levels deep. What fails, and how do you rewrite the traversal?
  • A grandchild is due earlier than its grandparent, but its parent is due later than the grandparent or has no deadline. Where does your code print the grandchild, and what would change if every task had to print before all ancestors due later than it?
  • Tasks are added, completed and reassigned after construction, and the method is called often. What would you maintain incrementally instead of recomputing on every call?