Javascript 筛选JSON中的一个特定节点,显示直接父节点和所有子节点
给定以下JSON对象Javascript 筛选JSON中的一个特定节点,显示直接父节点和所有子节点,javascript,json,Javascript,Json,给定以下JSON对象 const data = [ { "id": 1, "name": "Node 1", "children": [ { "id": 3, "name": "Node 1.1", "children": [ { "id": 6, "name": "Node 1.1.1", "children": [ { "id": 12, "name": "Node
const data = [
{ "id": 1, "name": "Node 1", "children": [
{ "id": 3, "name": "Node 1.1", "children": [
{ "id": 6, "name": "Node 1.1.1", "children": [
{ "id": 12, "name": "Node 1.1.1.1", "children": [] }
]
},
{ "id": 7, "name": "Node 1.1.2", "children": [
{ "id": 13, "name": "Node 1.1.2.1", "children": [] }
]
}
]
},
{ "id": 4, "name": "Node 1.2", "children": [
{ "id": 8, "name": "Node 1.2.1", "children": [] },
{ "id": 9, "name": "Node 1.2.2", "children": [
{ "id": 14, "name": "Node 1.2.2.1", "children": [] },
{ "id": 15, "name": "Node 1.2.2.2", "children": [] }
]
}
]
}
]
},
{ "id": 2, "name": "Node 2", "children": [
{ "id": 5, "name": "Node 2.1", "children": [
{ "id": 10, "name": "Node 2.1.1", "children": [] },
{ "id": 11, "name": "Node 2.1.2", "children": [
{ "id": 16, "name": "Node 2.1.2.1", "children": [] }
]
}
]
}
]
}
];
我希望能够通过ID找到一个特定的节点,一旦找到该节点,就可以得到它的直接父节点和所有子节点。例如,如果我想找到ID为9的节点(节点1.2.2),我希望它返回节点1
,节点1.2
,节点1.2.2
及其子节点,并忽略所有其他内容。我用这个findById
函数实现了部分功能
findById(data, id)
{
let node = '';
data.some((currentNode) => {
return node = id === currentNode.id ? currentNode : this.findById(currentNode.children, id);
});
return node;
}
就是这样叫的,
this.data = [this.findById(this.data, id)];
但它并不完全符合我的要求。它会找到正确的节点(在本例中为1.2.2)及其子节点(1.2.2.1和1.2.2.2),但不会找到其直接父节点(1.2和1)。如何将findById
函数更改为也包括直接父项
期望的输出是:
const found = [
{ "id": 1, "name": "Node 1", "children": [
{ "id": 4, "name": "Node 1.2", "children": [
{ "id": 9, "name": "Node 1.2.2", "children": [
{ "id": 14, "name": "Node 1.2.2.1", "children": [] },
{ "id": 15, "name": "Node 1.2.2.2", "children": [] }
]
}
]
}
]
}
];
第一个问题是,这是正确的数据结构吗?你能在链表中实现这一点吗?如果是这样,则可以对祖辈节点、父节点进行特定引用。如果数据相对较小,则搜索时间是线性的,插入和删除是线性的
class Node {
constructor(value){
this.value = value;
this.next = null;
this.children = [];
}
}
class LinkedList {
constructor() {
this.head = null;
this.tail = null;
this.size = 0
}
insert(value) {
let node = new Node(value);
if(!this.head) {
this.head = node;
} else {
this.tail.next = node;
}
this.tail = node;
this.size++;
}
findNode(value) {
let node = this.head;
while(!!node) {
if(node.value === value){
return node;
}
node = node.next;
}
return `no node with ${value} found`
}
forEach(callback) {
let node = this.head;
while(!!node) {
callback(node.value);
node = node.next;
}
}
print() {
if(!this.head) {
return null
} else {
let node = this.head;
while(!!node){
console.log(node.value);
node = node.next
}
}
您只需要存储递归函数的结果。要执行此操作,请将您的三元值分隔为if-else,如下所示:
函数findById(数据,id){
设node=null;
data.some((currentNode)=>{
if(id==currentNode.id){
返回节点=[currentNode];
}
const inItsTree=findById(currentNode.children,id);
if(inItsTree){
返回节点=[{…currentNode,子节点:inItsTree}];
}
});
返回节点;
}
const data=[{“id”:1,“name”:“Node 1”,“children”:[{“id”:3,“name”:“Node 1.1”,“children”:[{“id”:6,“name”:“Node 1.1.1”,“children”:[{“id”:12,“name”:“Node 1.1.1.1”,“children”:[]}},{“id”:7,“name”:“Node 1.1.2”,“children”:[{“id”:13,“name”:“Node 1.1.1.2.1”,“children id”:4,“name”:“Node 1.2”,“children{“id”:9,“名称”:“节点1.2.2”,“子节点”:[{“id”:14,“名称”:“节点1.2.2.1”,“子节点”:[]},{“id”:15,“名称”:“节点1.2.2”,“子节点”:[]}]},{“id”:2,“名称”:“节点2”,“子节点”:[{“id”:5,“名称”:“节点2.1”,“子节点”:[{“id”:10,“名称”:“节点2.1.1”,“子节点”[]},{“id”:11,“名称”:“节点2.1.2.2”,“子节点”:“{”16,“子节点”}]};
console.log(findById(data,9));
将findById方法修改为:
function findById(data, id, parent)
{
let node = '';
data.some((currentNode) => {
if(id === currentNode.id) {
node = currentNode;
} else {
parent.push(currentNode); // track parent node
node = this.findById(currentNode.children, id, parent);
}
return node;
});
return {node: node, parent: parent};
}
this.data = [this.findById(this.data, 6, [])];
console.log(this.data[0].node); // will give you current node with children
console.log(this.data[0].parent); // will give you array of parents node
递归是一种功能遗产,因此这里有一个使用函数风格的解决方案-
// identity : 'a -> 'a
const identity = x =>
x
// findById : (number, node array) -> node?
const findById = (q = 0, [ n, ...more ], exit = identity) =>
n === undefined
? false
: findById1 (q, n, exit)
|| findById (q, more, exit)
// findById1 : (number, node) -> node?
const findById1 = (q = 0, n = {}, exit = identity) =>
n.id === q
? exit (n)
: findById (q, n.children, r =>
exit ({...n, children: [ r ] })
)
它是这样工作的-
findById (9, data)
// { id: 1, name: "Node 1", children: [
// { id: 4, name: "Node 1.2", children: [
// { id: 9, name: "Node 1.2.2", children: [
// { id: 14, name: "Node 1.2.2.1", children: [] },
// { id: 15, name: "Node 1.2.2.2", children: [] }
// ]}
// ]}
// ]}
当找不到id时,将返回false
-
findById (99, data)
// false
展开下面的代码段,在您自己的浏览器中验证结果-
const identity=x=>
x
const findById=(q=0,[n,…更多],exit=identity)=>
n==未定义
?错误
:findById1(q、n、出口)
||findById(q,更多,退出)
const findById1=(q=0,n={},exit=identity)=>
n、 id==q
?出口(n)
:findById(q,n.children,r=>
退出({…n,子项:[r]})
)
常量数据=
[{id:1,名称:“节点1”,子节点:[{id:3,名称:“节点1.1”,子节点:[{id:6,名称:“节点1.1.1”,子节点:[{id:12,名称:“节点1.1.1”,子节点:[]},{id:7,名称:“节点1.1.2”,子节点:[{id:13,名称:“节点1.1.2.1”,子节点:[]}}}},{id:4,名称:“节点1.2”,子节点:[{id:8,名称:“节点1.2.1”,子节点:[]2,子节点:[][{id:14,名称:“节点1.2.2.1”,子节点:[]},{id:15,名称:“节点1.2.2”,子节点:[]}},{id:2,名称:“节点2”,子节点:[{id:5,名称:“节点2.1”,子节点:[{id:10,名称:“节点2.1.1”,子节点:[]},{id:11,名称:“节点2.1.2”,子节点:[{id:16,名称:“节点2.1.2.1”,子节点:[]}]
console.log(findById(9,数据))
//{id:1,名称:“节点1”,子节点:[
//{id:4,名称:“节点1.2”,子节点:[
//{id:9,名称:“节点1.2.2”,子节点:[
//{id:14,名称:“节点1.2.2.1”,子节点:[]},
//{id:15,名称:“节点1.2.2.2”,子节点:[]}
// ]}
// ]}
// ]}
console.log(findById(99,数据))
//false
这正是我想要的,现在只需让它与我的其余代码一起工作,谢谢!我很高兴能帮助您:)没有JSON对象这样的东西-JSON始终是字符串“删除是固定时间“-这听起来不正确,也没有在你的答案中说明。也许就把那部分删掉吧?@user633183,你是对的,按id查找时是线性的。