Javascript 筛选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

给定以下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 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查找时是线性的。