Given an object or an array obj and a function fn, return a filtered object or array filteredObject.
Function deepFilter should perform a deep filter operation on the obj. The deep filter operation should remove properties for which the output of the filter function fn is false, as well as any empty objects or arrays that remain after the keys have been removed.
If the deep filter operation results in an empty object or array, with no remaining properties, deepFilter should return undefined to indicate that there is no valid data left in the filteredObject.
Example 1:
Input: obj = [-5, -4, -3, -2, -1, 0, 1], fn = (x) => x > 0 Output: [1] Explanation: All values that were not greater than 0 were removed.
Example 2:
Input:
obj = {"a": 1, "b": "2", "c": 3, "d": "4", "e": 5, "f": 6, "g": {"a": 1}},
fn = (x) => typeof x === "string"
Output: {"b":"2","d":"4"}
Explanation: All keys with values that were not a string were removed. When the object keys were removed during the filtering process, any resulting empty objects were also removed.
Example 3:
Input: obj = [-1, [-1, -1, 5, -1, 10], -1, [-1], [-5]], fn = (x) => x > 0 Output: [[5,10]] Explanation: All values that were not greater than 0 were removed. When the values were removed during the filtering process, any resulting empty arrays were also removed.
Example 4:
Input: obj = [[[[5]]]], fn = (x) => Array.isArray(x) Output: undefined
Constraints:
fn is a function that returns a boolean valueobj is a valid JSON object or array2 <= JSON.stringify(obj).length <= 105Problem Overview: Deep Object Filter asks you to recursively process a nested structure (objects and arrays) and remove values that do not satisfy a predicate function fn. Primitive values are checked directly with the predicate, while arrays and objects must be traversed deeply so that only valid elements remain in the final structure.
Approach 1: Recursive DFS Traversal (O(n) time, O(h) space)
The most natural solution treats the input as a tree of values and performs a depth‑first traversal. If the current value is an array, iterate through each element, recursively filter it, and keep only the results that are still valid. If the value is an object, iterate through its keys and recursively filter each property, deleting keys whose filtered result is invalid. For primitives, simply evaluate fn(value) and return the value only when the predicate passes. This approach processes each node exactly once, giving O(n) time complexity where n is the number of values in the structure, and O(h) recursion stack space where h is the maximum nesting depth. This pattern is common in problems involving recursion and nested data traversal.
Approach 2: Iterative Stack Traversal (O(n) time, O(n) space)
You can replace recursion with an explicit stack to simulate depth‑first traversal. Push the root node onto a stack along with a reference to its parent container. While the stack is not empty, pop a node, inspect its type, and process arrays or objects by pushing their children back onto the stack. After evaluating children, remove entries that fail the predicate or become empty after filtering. This avoids recursion depth limits and can be easier to control in environments where stack overflow is a concern. The algorithm still visits every element once, resulting in O(n) time complexity and up to O(n) auxiliary space for the stack and intermediate references. The traversal pattern is similar to iterative depth-first search used for tree structures.
Recommended for interviews: The recursive DFS approach is what most interviewers expect. It shows you understand how to traverse nested data structures and apply transformations during recursion. Mentioning the iterative stack variant demonstrates deeper understanding of traversal mechanics and recursion limits. If the discussion touches JavaScript behavior, highlighting how arrays and objects are processed differently in JavaScript can also strengthen your explanation.
TypeScript
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Recursive DFS Traversal | O(n) | O(h) | Best general solution for nested arrays/objects when recursion depth is manageable |
| Iterative Stack Traversal | O(n) | O(n) | When avoiding recursion limits or when explicit traversal control is needed |
LeetCode was HARD until I Learned these 15 Patterns • Ashish Pratap Singh • 1,002,273 views views
Watch 9 more video solutions →Practice Deep Object Filter with our built-in code editor and test cases.
Practice on FleetCodePractice this problem
Open in Editor