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 > 0Output: [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 > 0Output: [[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:
fnis a function that returns a boolean valueobjis 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);
};
