2823. 深度对象筛选 🔒
2823. 深度对象筛选 🔒
题目
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:
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 <= 10^5
题目大意
给定一个对象 obj
和一个函数 fn
,返回一个经过筛选的对象 filteredObject
。
函数 deepFilter
应该在对象 obj
上执行深度筛选操作。深度筛选操作应该移除筛选函数 fn
输出为 false
的属性,以及在键被移除后仍然存在的任何空对象或数组。
如果深度筛选操作导致对象或数组为空,没有剩余属性,deepFilter
应该返回 undefined
,表示在 filteredObject
中没有有效数据。
示例 1:
输入:
obj = [-5, -4, -3, -2, -1, 0, 1], fn = (x) => x > 0
输出:[1]
解释: 所有不大于 0 的值都被移除。
示例 2:
输入:
obj = {"a": 1, "b": "2", "c": 3, "d": "4", "e": 5, "f": 6, "g": {"a": 1}}, fn = (x) => typeof x === "string"
输出:
解释: 所有值不是字符串的键都被移除。在筛选过程中移除键后,任何导致为空的对象也被移除。
示例 3:
输入:
obj = [-1, [-1, -1, 5, -1, 10], -1, [-1], [-5]], fn = (x) => x > 0
输出:[[5,10]]
解释: 所有不大于 0 的值都被移除。在筛选过程中移除值后,任何导致为空的数组也被移除。
示例 4:
输入:
obj = [[[[5]]]], fn = (x) => Array.isArray(x)
输出: undefined
提示:
fn
是一个返回布尔值的函数obj
是一个有效的 JSON 对象2 <= JSON.stringify(obj).length <= 10**5
解题思路
定义递归函数
dfs
,用于对传入的对象或数组进行深度筛选,会对obj
中的每个属性进行递归检查,符合条件的保留,不符合的剔除。递归处理数组:
- 在
dfs
函数内,首先检查obj
是否是数组。 - 如果是数组,则对每个元素调用
dfs
递归处理并存储到新数组res
中。 - 之后,通过
filter
去除undefined
项,仅保留有效数据。 - 如果
res
数组有内容,返回res
,否则返回undefined
。
- 在
递归处理对象:
- 如果
obj
是对象,则创建一个空对象res
,然后遍历obj
的每个属性。 - 对每个属性调用
dfs
递归处理,并将结果存储在filteredValue
中。 - 如果
filteredValue
不为undefined
,将该属性和值保留在res
中。 - 遍历完成后,如果
res
不为空,返回res
;否则返回undefined
。
- 如果
处理基本数据类型:
- 对于非对象和非数组的值,直接调用筛选函数
fn
。 - 如果
fn
返回true
,保留该值; - 否则返回
undefined
表示不保留。
- 对于非对象和非数组的值,直接调用筛选函数
整个
dfs
处理完成后,返回筛选后的结果。
复杂度分析
- 时间复杂度:
O(n)
,其中n
是对象的节点数,需要递归遍历每个节点。 - 空间复杂度:
O(d)
,其中d
是对象的最大嵌套深度,主要是递归调用栈的开销。
代码
/**
* @param {Object} obj
* @param {Function} fn
* @return {Object}
*/
var deepFilter = function (obj, fn) {
const dfs = (obj) => {
// 递归处理数组
if (Array.isArray(obj)) {
let res = obj.map(dfs).filter((i) => i !== undefined);
return res.length > 0 ? res : undefined;
}
// 递归处理对象
if (typeof obj == 'object' && obj != null) {
let res = {};
for (let key of Object.keys(obj)) {
const filteredValue = dfs(obj[key]);
if (filteredValue !== undefined) {
res[key] = filteredValue;
}
}
return Object.keys(res).length > 0 ? res : undefined;
}
// 处理基本数据类型
return fn(obj) ? obj : undefined;
};
return dfs(obj);
};