如果对象与任何选定的 ID 都不匹配,则从嵌套树中移除对象

Remove object from nested tree if it doesn't match any of the selected id

我有一个选定的数组

this.selectedArray = ["1:Tree", "2:PT", "5:PT - DD", "11:PT - C", "3:SAC", "7:SAC - DR", "6:SAC - DDE"]

和具有子项的树结构:

this.root =    
{"children": [
   {"children": [
     {
      "children": [],
      "id": 12,
      "name": "PT - D"
    },
    {
      "children": [
        {
          "children": [],
          "id": 8,
          "name": "PT-33"
        },
        {
          "children": [],
          "id": 10,
          "name": "PT-62"
        },
        {
          "children": [],
          "id": 9,
          "name": "PT-52"
        }
      ],
      "id": 4,
      "name": "PT - 32"
    },
    {
      "children": [
        {
          "children": [],
          "id": 11,
          "name": "PT - C"
        }
      ],
      "id": 5,
      "name": "PT - DD"
    }
  ],
  "id": 2,
  "name": "PT"
},
{
  "children": [
    {
      "children": [],
      "id": 7,
      "name": "SAC - DR"
    },
    {
      "children": [],
      "id": 6,
      "name": "SAC - DE"
    }
  ],
  "id": 3,
  "name": "SAC"
}
],
 "id": 1,
 "name": "Tree"
}

如果 node.Id + ':' + node.name 与 this.selectedArray 中的任何项目都不匹配,我想从树中删除该节点。

我无法找到一种算法,该算法允许我从深度嵌套的树中删除与 this.selected 中的任何项目都不匹配的所有对象数据。

代码如下:

 setSearchResult(selectedArray) {
    if (!!selected) {
        let this.tree = JSON.parse(JSON.stringify(this.root));
        this.topLevelGroups = this.removeFromTree(this.tree, selectedArray, null, null);
    }
}

removeFromTree(parent, selectedArray, grandParent, idx) {
    let { name, id, children } = parent;
    let parentId = id + ':' + name;
    if (!!selectedArray) {
        if (!selectedArray.includes(parentId)) {
            if (grandParent) {
                grandParent.children.splice(idx, 1);
            } 
            else return null;
        }
        if (!!parent && !!children) {
            for (let i = 0; i < children.length; i++) {
                this.removeFromTree(children[i], selectedArray, parent, i);
            }
        }
    }
    return this.tree.children;
  }

我认为问题是在执行具有 this.slice 的代码后,它将 return 并且不会转到其兄弟。有什么建议吗?

一个简单的递归过滤函数,因为你在你的selectedArray中使用字符串你可以很容易地使用Set来测试 一个节点。

const tags = new Set(selectedArray);

function filterArray ({ children, id, name }) {
    const tag = `${id}:${name}`;
    if (tags.has(tag)) {
        return {
            id,
            name,
            children: children.map(filterArray).filter((child) => child !== null)
        };
    }
    return null;
}


const output = filterArray(root);
console.log(JSON.stringify(output, null, 4));

您可以采用非变异方法并通过尊重子项来减少数组。

此解决方案将所需 id 的散列 table 作为键,将 name 作为 selected 数组拆分值中的值。

结果只包含已知节点。

const
    filter = (r, { children = [], ...o }) => {
        if (nodes[o.id] !== o.name) return r;
        children = children.reduce(filter, []);
        r.push(children.length ? { ...o, children } : o);
        return r;
    },
    selected = ["1:Tree", "2:PT", "5:PT - DD", "11:PT - C", "3:SAC", "7:SAC - DR", "6:SAC - DDE"],
    nodes = selected.reduce((r, s) => {
        var [k, v] = s.split(':');
        r[k] = v;
        return r;
    }, {}),
    tree = { children: [{ children: [{ children: [], id: 12, name: "PT - D" }, { children: [{ children: [], id: 8, name: "PT-33" }, { children: [], id: 10, name: "PT-62" }, { children: [], id: 9, name: "PT-52" }], id: 4, name: "PT - 32" }, { children: [{ children: [], id: 11, name: "PT - C" }], id: 5, name: "PT - DD" }], id: 2, name: "PT" }, { children: [{ children: [], id: 7, name: "SAC - DR" }, { children: [], id: 6, name: "SAC - DE" }], id: 3, name: "SAC" }], id: 1, name: "Tree" },
    result = tree.children = tree.children.reduce(filter, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }