基于键值

时间:2017-10-07 20:57:47

标签: javascript arrays

我已经打破了几个小时的脑袋,想知道如何根据键值在多维数组中递归删除对象。我需要在下面的示例数组中删除包含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()

2 个答案:

答案 0 :(得分:4)

将数组拼接出数组会改变数组的长度,并且难以使用for循环进行迭代。通常的解决方案是向后迭代数组,这使得长度无关紧要(0索引是停止点)。

但是,我建议采用另一种方法,递归重建条目树,而不使用Array#reduce要排除的项目。如果一个对象包含一个子数组(根据预定义的childrenProp),则使用Object#assign创建一个新对象,并在过滤后添加子数组。

&#13;
&#13;
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;
&#13;
&#13;

答案 1 :(得分:0)

您可以使用函数检查是否定义了"exclude"属性,如果该元素为true delete,则递归迭代对象的"content"属性,调用delete"exclude" true的位置,使用JSON.stringify()JSON.parse()String.prototype.replace()删除从数组中投射到null的空索引

&#13;
&#13;
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;
&#13;
&#13;