问题描述:
仔细看上图数据结构会发现value和parent是有关联的,这种关联非常类似于树型数据,那问题来了,这种数据是可以有n层数据的,要怎么查找并对树型数据进行处理就成了1大问题,我想实现只需要通过某个value值就可以获取到往上的每一个分支数据并可以进行处理,比如对show属性赋值什么的,往上查找有n个分支的可能(n个的意思是往上不知道有多少层),然后往下只需要找1个分支(只需要通
过value匹配一下parent就可以)。for循环应该没办法处理树型数据,树型数据应该要使用递归算法来处理,希望能给一个正解。
结构描述:
value -- 类似于ID
parent -- 类似于父级ID
思路:
1.要想通过某个value来找到上级,应该是先匹配当前value的对象,然后通过下标或对象拿到当前对象的parent,最后再用parent去匹配value就可以匹配到父级了。(问题在这里,这个思路只能匹配到一个分支,但是我想匹配到往上的n个分支)
2.要想通过某个value来找到子级,应该是直接用value匹配parent,这样就可以找到所有子级了。(这个思路只能匹配到一个分支)
找父节点一般只有一条路径吧,为什么会出现多个呢?一个节点一般只有一个父节点,难道还要找父节点兄弟节点的子节点?
找指定节点所有子节点简单,将这个节点的value和遍历到的子节点的value全部压入数组,是否子节点遍历到的节点的parent是否在数组即可。
let list = [
{name:'全部分类', value: null, parent: null },
{ name: '视频', value: '682395', parent: null },
{ name: '音频', value: '971824', parent: null },
{ name: '流量', value: '891628', parent: null },
{ name: '编辑', value: '276312', parent: null },
{ name: '原创', value: '785312', parent: '682395' },
{ name: '改编', value: '981726', parent: '682395' },
{ name: '美食', value: '217241', parent: '785312' },
{ name: '科技', value: '783102', parent: '785312' },
{ name: '动画', value: '412842', parent: '981726' },
]
function getParentNodes(value,list) {//只有一条,没搞清楚找父节点会有多个分支
var node = list.find(i => i.value == value);
if (node) {//找到节点
var pNodes = [];//如果需要放入查找的节点这里改为var pNodes = [node];
while (node = list.find(i => i.value == node.parent)) {
pNodes.unshift(node);//将父节点前插
if (node.value === null) break;//找到顶级节点退出
}
return pNodes;
}
return null;//找不到需要查找的value返回null,注意判断getParentNodes函数返回值
}
function visitChildren(value, list) {
var index = list.findIndex(i => i.value == value);
if (index != -1) {//找到节点
var pids = [list[index].value];//父节点集合
for (var i = index + 1; i < list.length; i++) {
if (pids.includes(list[i].parent)) {
console.log(list[i]);//子节点
pids.push(list[i].value);//加入父id
}
}
}
}
你这是需要根据value,parent 关系把生成树形结构的数据吧?用递归实现的,试试看。
function initTreeData(treeList) {
let treeData = {};
function query(list, i) {
list.forEach((v) => {
if (v.value === i.parent) v.children = [...(v?.children ?? []), i];
if (list?.children) query(list.children, i);
});
}
treeList.forEach((i) => {
if (!i.value && !i.parent) {
treeData = i;
treeData.children = treeList.filter(
(item) => item.value && !item.parent
);
return;
}
if (i?.value && i?.parent) query(treeList, i);
});
return treeData;
},
const data = [
{ name: '全部分类', value: null, parent: null },
{ name: '视频', value: '682395', parent: null },
{ name: '音频', value: '971824', parent: null },
{ name: '流量', value: '891628', parent: null },
{ name: '编辑', value: '276312', parent: null },
{ name: '原创', value: '785312', parent: '682395' },
{ name: '改编', value: '981726', parent: '682395' },
{ name: '美食', value: '217241', parent: '785312' },
{ name: '科技', value: '783102', parent: '785312' },
{ name: '动画', value: '412842', parent: '981726' },
]
const findParent = (child) => {
const target = data.find(item => item.value == child.parent)
if(target != child)
return target;
else
return null;
}
data.forEach(item => {
const parent = findParent(item)
if(parent) {
if(!parent.children)
parent.children = [];
parent.children.push(item);
//使用对象来代替原来的字符串,如果不喜欢可以使用其它字段名称
item.parent = parent;
}
});
console.log(data);
//查找某个指定值的所有父级并设置字段值
let result = data.find(item => item.value == "981726")
let target = result
do {
target.show = true
target = target.parent;
} while(target != null)
//对于子级最后使用父级的show来判断是否显示,parent.show || child.show,不建议直接设置,如果硬要设置
const setChildrenProperties = (parent, setter) => {
parent.children && parent.children.forEach(child => {
setter(child);
setChildrenProperties(child, setter);
})
}
setChildrenProperties(result, child => child.show = true);
```
如果要查找某个value的父级,可以使用递归函数,每次通过当前value的对象的parent去匹配数据中的value,直到没有对象的parent为止。对于每一层递归,都可以记录父级的信息,最终返回往上的n个分支的信息。
如果要查找某个value的子级,可以遍历整个数据集,匹配所有parent与当前value相同的对象,最终得到所有子级的信息。
可以采用队列加递归的方式处理,这个肯定不能简单循环解决。
递归算法是可以递归往上寻找父级,也可以递归往下寻找子级的。
基于以上思路,我们可以写一个递归函数,每次把当前的value当做参数传递给递归函数,递归函数内部先判断当前的value是否满足条件,如果满足就进行处理,否则递归查找它的父级。如果父级不存在,则递归结束。
对于寻找子级的情况,我们可以把当前的value当做参数传递给递归函数,递归函数内部先判断当前的value是否满足条件,如果满足就进行处理,否则递归查找它的子级。如果子级不存在,则递归结束
const data = [ {value: 1, parent: 0}, {value: 2, parent: 1}, {value: 3, parent: 1}, {value: 4, parent: 2}, {value: 5, parent: 3},];
const findParent = (value) => {
let result = [];
for (let i = 0; i < data.length; i++) {
if (data[i].value === value) {
let parent = data[i].parent;
result.push(data[i]);
while (parent !== 0) {
for (let j = 0; j < data.length; j++) {
if (data[j].value === parent) {
result.push(data[j]);
parent = data[j].parent;
break;
}
}
}
break;
}
}
return result.reverse();
};
const findChildren = (value) => {
let result = [];
for (let i = 0; i < data.length; i++) {
if (data[i].parent === value) {
result.push(data[i]);
}
}
return result;
};
console.log(findParent(4));
// Output: [ { value: 4, parent: 2 }, { value: 2, parent: 1 }, { value: 1, parent: 0 } ]
console.log(findChildren(1));
// Output: [ { value: 2, parent: 1 }, { value: 3, parent: 1 } ]
public class TreeNode {
int value;
int parent;
// 其他属性
// ...
}
public class Tree {
List<TreeNode> nodes = new ArrayList<>();
// 查询某个节点的所有父级节点
public List<TreeNode> getParents(int value) {
TreeNode node = findNode(value);
List<TreeNode> parents = new ArrayList<>();
while (node.parent != -1) {
node = findNode(node.parent);
parents.add(node);
}
return parents;
}
// 查询某个节点的所有子级节点
public List<TreeNode> getChildren(int value) {
List<TreeNode> children = new ArrayList<>();
for (TreeNode node : nodes) {
if (node.parent == value) {
children.add(node);
}
}
return children;
}
// 查询节点
private TreeNode findNode(int value) {
for (TreeNode node : nodes) {
if (node.value == value) {
return node;
}
}
return null;
}
}