一、核心
本质上就是对树状结构数据的一个递归遍历+数据比对+数据筛选(保留)
难点在于非扁平化的树结构在筛选时保留时的取舍,这里的关键是,只要节点存在keyword,那么根节点到当前节点的树结构就必须保留,所以对节点的操作必须放在遍历后
二、遍历概念
这里有必要回顾一下数据结构中的二叉树的遍历方式,开发中最常用还是前序遍历(根左右),遍历的目的是访问树结构的每一个节点(且只访问一次),对节点进行一些操作(新增,修改,删除)
前序遍历可以满足大多数开发场景。但如果涉及到树结构的断层拼接、树结构的模糊查询等等根据条件多层级保留的场景,前序遍历就很无力。因为操作树结构是children渐渐往外发散的,从前往后遍历操作,会丢失掉父层级
三、实现思路
后续遍历每个节点,遍历完之后再 左右根 顺序做判断筛选。遍历返回值为临时数组,存放包含keyword的树节点
叶子节点终止遍历(children.length==0)
当前节点两种情况:
- 子节点有返回值,直接纳入临时数组,无需多言,只要包含即这条路径必须保留
- 子节点无返回值,判断当前节点是否包含keyword
四、实现代码及效果
这里用JS实现一下这个过程,其他强类型语言只需要加上变量的类型限制即可,方法思路一致
/**
* 根据关键字检索专题
* @param String searchValue 输入的关键字
* @param treeNode searchTopicCatalogs 待搜索的树结构
* @returns {*}treeNode res
* @private
* 递归查询检索
*/
const recursionHandler = (searchValue, searchTopicCatalogs) => {
let tempSearchArr = [];
searchTopicCatalogs.forEach((treeNode) => {
if (treeNode.children && treeNode.children.length > 0) {
// 后序遍历
let tempArr = this.recursionHandler(searchValue, treeNode.children);
// 当前树节点的子节点存在匹配字符,直接纳入数组
if (tempArr.length > 0) {
tempSearchArr.push(treeNode);
}
//当前树节点存在匹配字符
else {
if (treeNode.title.indexOf(searchValue) >= 0) {
tempSearchArr.push(treeNode);
}
}
}
// 叶子节点
else {
// 当前树节点存在匹配字符
if (treeNode.title.indexOf(searchValue) >= 0) {
tempSearchArr.push(treeNode);
}
}
});
return tempSearchArr;
}