我有一个深度嵌套的对象,需要搜索以删除某些键。要删除的键存储在removeKeys
数组中指示的数组中。
当前,该函数仅过滤顶级对象,但将其余部分按比例缩放,只是不过滤子对象。我如何适当减少整个对象以获得所需的输出?
初始未过滤对象:
let item = {
"label": "test",
"id": "test",
"styles": {
"label": "Styles",
"styles": {
"test": {
"test": "test",
"label": "test",
"test1": {
"label": "test",
"image": {
"label": "test",
"type": "test",
"value": "test",
"autoSelect": "",
"id": ""
}
}
}
}
},
"test": {
"label": "test",
"test": []
}
}
要从对象中删除的键:
const removeKeys = ["label", "type", "autoSelect"];
用于过滤嵌套对象的递归函数:
let filterObject = filterNestObject(item);
function filterNestObject(item) {
return Object.keys(item)
.filter(key => {
if (typeof item[key] === 'object') filterNestObject(item[key]);
if (!removeKeys.includes(key)) return true;
return false
})
.reduce((object, key) => {
return {
...object,
[key]: item[key]
};
}, {});
}
预期结果将是:
{
"id": "test",
"styles": {
"styles": {
"test": {
"test": "test",
"test1": {
"image": {
"value": "test",
"id": ""
}
}
}
}
},
"test": {
"test": []
}
}
答案 0 :(得分:1)
这有点hacky,性能也不是很好,所以如果您要处理非常大的对象图,这可能不是一个好的解决方案,但这是在{{3}中使用replacer
回调的单线解决方案}:
JSON.parse(JSON.stringify(audience, (k, v) => removeKeys.includes(k) ? undefined : v));
演示:
let audience = {
"label": "test",
"id": "test",
"styles": {
"label": "Styles",
"styles": {
"test": {
"test": "test",
"label": "test",
"test1": {
"label": "test",
"image": {
"label": "test",
"type": "test",
"value": "test",
"autoSelect": "",
"id": ""
}
}
}
}
},
"test": {
"label": "test",
"test": []
}
}
const removeKeys = ["label", "type", "autoSelect"];
let newAudience = JSON.parse(JSON.stringify(audience, (k, v) => removeKeys.includes(k) ? undefined : v));
console.log(newAudience);
同一行中,如果要从JSON字符串解析原始对象,则可以使用JSON.stringify
中的reviver
回调:
let jsonString = `{
"label": "test",
"id": "test",
"styles": {
"label": "Styles",
"styles": {
"test": {
"test": "test",
"label": "test",
"test1": {
"label": "test",
"image": {
"label": "test",
"type": "test",
"value": "test",
"autoSelect": "",
"id": ""
}
}
}
}
},
"test": {
"label": "test",
"test": []
}
}`
const removeKeys = ["label", "type", "autoSelect"];
const audience = JSON.parse(jsonString, (k, v) => removeKeys.includes(k) ? undefined : v);
console.log(audience);
答案 1 :(得分:1)
代码中的错误是您在filter
回调中进行了递归调用。但是,您将丢失从递归调用返回的对象。而是在reduce
回调中创建它。
一个较小的更正:要测试一个值是否是一个对象,这样做还不够typeof item[key] === "object"
,因为null
也会通过该测试。这是改编后的代码:
function filterNestObject(item) {
return Object.keys(item)
.filter(key => !removeKeys.includes(key))
.reduce((acc, key) => {
return Object.assign(acc, {
[key]: Object(item[key]) === item[key] ? filterNestObject(item[key]) : item[key]
});
}, Array.isArray(item) ? [] : {});
}
const item = {"label": "test","id": "test","styles": {"label": "Styles","styles": {"test": {"test": "test","label": "test","test1": {"label": "test","image": {"label": "test","type": "test","value": "test","autoSelect": "","id": ""}}}}},"test": {"label": "test","test": []}};
const removeKeys = ["label", "type", "autoSelect"];
const filterObject = filterNestObject(item);
console.log(filterObject);
答案 2 :(得分:1)
您可以采用迭代和递归的方法来过滤键并构建新对象。
function remove(object, keys) {
return Object.assign({}, ...Object.keys(object)
.filter(k => !keys.includes(k))
.map(k => ({ [k]: object[k] && typeof object[k] === 'object' ? remove(object[k], keys) : object[k] }))
);
}
var item = { label: "test", id: "test", styles: { label: "Styles", styles: { test: { test: "test", label: "test", test1: { label: "test", image: { label: "test", type: "test", value: "test", autoSelect: "", id: "" } } } } }, test: { label: "test", test: [] } },
removeKeys = ["label", "type", "autoSelect"];
console.log(remove(item, removeKeys));
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 3 :(得分:0)
您正在递归地调用该函数,但是您对该递归调用返回的结果不做任何事情。您必须使用过滤后的值覆盖子键:
let item = {
"label": "test",
"id": "test",
"styles": {
"label": "Styles",
"styles": {
"test": {
"test": "test",
"label": "test",
"test1": {
"label": "test",
"image": {
"label": "test",
"type": "test",
"value": "test",
"autoSelect": "",
"id": ""
}
}
}
}
},
"test": {
"label": "test",
"test": []
}
}
const removeKeys = ["label", "type", "autoSelect"];
let filterObject = filterNestObject(item);
function filterNestObject(item) {
return Object.keys(item)
.filter(key => {
if (typeof item[key] === 'object') {
// set the key to the filtered result returned by the recursively called function
item[key] = filterNestObject(item[key]);
}
if (!removeKeys.includes(key)) return true;
return false
})
.reduce((object, key) => {
return {
...object,
[key]: item[key]
};
}, {});
}
console.log(filterNestObject(item));
答案 4 :(得分:0)
我可能会使用Object.entries
,filter
+ includes
,map
和Object.fromEntries
-
const removeDeepKeys = (keys = [], o = {}) =>
Object (o) === o
? Object
.fromEntries
( Object
.entries (o)
.filter (([ k, _ ]) => ! keys .includes (k))
.map (([ k, v ]) => [ k, removeDeepKeys (keys, v) ])
)
: o
在您的item
上尝试-
removeDeepKeys ([ 'label', 'type', 'autoSelect' ], item)
输出-
{
"id": "test",
"styles": {
"styles": {
"test": {
"test": "test",
"test1": {
"image": {
"value": "test",
"id": ""
}
}
}
}
},
"test": {
"test": {}
}
}
编辑以支持数组-
const removeDeepKeys = (keys = [], o = {}) =>
Array .isArray (o)
? o .map (v => removeKeys (keys, v))
: Object (o) === o
? Object
.fromEntries
( Object
.entries (o)
.filter (([ k, _ ]) => ! keys .includes (k))
.map (([ k, v ]) => [ k, removeDeepKeys (keys, v) ])
)
: o
答案 5 :(得分:0)
前一段时间,我尝试创建一种cloneObj()
方法,以使用新的提议Object.fromEntries()来深克隆对象。您可以在下一个链接上查看我当时提出的问题,以供参考:Deep-Cloning an object using Object.fromEntries()
我相信可以略微修改此方法以适合您的目标:
const item = {"label": "test","id": "test","styles": {"label": "Styles","styles": {"test": {"test": "test","label": "test","test1": {"label": "test","image": {"label": "test","type": "test","value": "test","autoSelect": "","id": ""}}}}},"test": {"label": "test","test": [{label: "foo", test: "test4"}]}};
const removeKeys = ["label", "type", "autoSelect"];
const cloneObjWithoutKeys = (obj, keys) =>
{
if (Object(obj) !== obj)
return obj;
else if (Array.isArray(obj))
return obj.map(o => cloneObjWithoutKeys(o, keys));
return Object.fromEntries(
Object.entries(obj)
.filter(([k, v]) => !keys.includes(k))
.map(([k, v]) => ([k, cloneObjWithoutKeys(v, keys)])
));
}
console.log(cloneObjWithoutKeys(item, removeKeys));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
请注意,这还将遍历对象的内部数组以过滤出所需的键。