我已经打破了几个小时的脑袋,想知道如何根据键值在多维数组中递归删除对象。我需要在下面的示例数组中删除包含exclude: true
的所有对象。我尝试使用递归函数循环项目,但我正在将这些项目拼接出数组......
// example multidimensional array with objects
let array: Object[] = [
// exclude on level 1
{
name: 'A',
exclude: true,
content: [
{
name: 'A-A',
},
{
name: 'A-B',
exclude: true,
},
{
name: 'A-C',
content: [
{
name: 'A-C-A',
}
]
}
]
},
// exclude on level 2
{
name: 'A',
content: [
{
name: 'A-A',
},
{
name: 'A-B',
exclude: true,
},
{
name: 'A-C',
content: [
{
name: 'A-C-A',
}
]
}
]
},
// exclude on level 2 and 3
{
name: 'A',
content: [
{
name: 'A-A',
},
{
name: 'A-B',
exclude: true,
},
{
name: 'A-C',
content: [
{
name: 'A-C-A',
exclude: true,
}
]
}
]
}
]
// run function
deleteItems(array);
// path is an array containing the indexes of the items
// e.g. path = [0, 0, 0] --> array[0][0][0]
function deleteItems(arr, path_index: number = 0, path: any[] = [0]): void {
// loop through arr
for (let i = 0; i < arr.length; i++) {
// get item
let item = arr[i];
// set path
path[path_index] = i;
// delete here somehow the item with corresponding path
if (item['exclude']) {
console.log('path', path);
}
// recursion
if ('content' in item) {
// +2 to path index (1. for content, 2. for i)
let path_index_ref = path_index + 2;
// create new path so old path does not get changed
let path_ref = path.slice();
path_ref.push('content');
this.deleteFlowchartItem(item['content'], path_index_ref, path_ref);
} // if content
} // for
} // deleteFlowchartItem()
答案 0 :(得分:4)
将数组拼接出数组会改变数组的长度,并且难以使用for循环进行迭代。通常的解决方案是向后迭代数组,这使得长度无关紧要(0索引是停止点)。
但是,我建议采用另一种方法,递归重建条目树,而不使用Array#reduce要排除的项目。如果一个对象包含一个子数组(根据预定义的childrenProp
),则使用Object#assign创建一个新对象,并在过滤后添加子数组。
const array = [{"name":"A","exclude":true,"content":[{"name":"A-A"},{"name":"A-B","exclude":true},{"name":"A-C","content":[{"name":"A-C-A"}]}]},{"name":"A","content":[{"name":"A-A"},{"name":"A-B","exclude":true},{"name":"A-C","content":[{"name":"A-C-A"}]}]},{"name":"A","content":[{"name":"A-A"},{"name":"A-B","exclude":true},{"name":"A-C","content":[{"name":"A-C-A","exclude":true}]}]}];
const recursiveFilter = (arr, predicate, childrenProp) => arr.reduce((a, o) => {
// if predicate fails don't include the object and it's children
if(!predicate(o)) {
return a;
}
const obj = Array.isArray(o[childrenProp]) ? // if there is a sub array
Object.assign({}, o, { // create a new object from the original properties with the filtered sub array
[childrenProp]: recursiveFilter(o[childrenProp], predicate, childrenProp)
})
:
o; // or use the original object
a.push(obj);
return a;
}, []);
const result = recursiveFilter(array, ({ exclude }) => !exclude, 'content');
console.log(result);
&#13;
答案 1 :(得分:0)
您可以使用函数检查是否定义了"exclude"
属性,如果该元素为true delete
,则递归迭代对象的"content"
属性,调用delete
在"exclude"
true
的位置,使用JSON.stringify()
,JSON.parse()
和String.prototype.replace()
删除从数组中投射到null
的空索引
let array = [{"name":"A","exclude":true,"content":[{"name":"A-A"},{"name":"A-B","exclude":true},{"name":"A-C","content":[{"name":"A-C-A"}]}]},{"name":"A","content":[{"name":"A-A"},{"name":"A-B","exclude":true},{"name":"A-C","content":[{"name":"A-C-A"}]}]},{"name":"A","content":[{"name":"A-A"},{"name":"A-B","exclude":true},{"name":"A-C","content":[{"name":"A-C-A","exclude":true}]}]}];
const fn = (o, arr, x = "exclude", it = "content") => {
if (o[x] === true) {
delete arr[arr.findIndex(obj => JSON.stringify(obj) === JSON.stringify(o))];
} else {
if (Array.isArray(o[it])) {
o.content.forEach(obj => fn(obj, o[it]))
}
}
}
array.forEach(o => fn(o, array));
array = JSON.parse(JSON.stringify(array).replace(/null,|null\b/g, ""));
console.log(array);
&#13;