简体   繁体   中英

How to compare parent and child record in nested array?

I am having a nodes like below in hierarchical structure :

Node - 1
     Node-1-1
       Node-1-1-1

Now I want to check whether connections is define or not between parent and child nodes.

Connections between parent and child is define like below for eg between Node-1 and Node-1-1 :

"connections": {
          "joins": [
            {
              "parent": "Node-1",
              "child": "Node-1-1"
            }
          ]
        }

If there exist at least 1 connection ( 1 record in joins property of connections ) between parent and child nodes then it's fine else I want to show alert to user and would like to return from the iterate function immediately on encounter of no connection between nodes.

So unless and until I get a response from iterate function(ie iterate function is not completed) I don't want to increment my id that is why I am passing callback to iterate function and would like to return response.

As there is no connections between Node-1-1 and Node-1-1-1 so I would like to show alert to user because there is no record in joins property of connections.

But problem is I am not getting how to compare every parent and child nodes and how to manage this callback in recursive structure.

 var records = [ { "name": "Node-1", "nodes": [ { "name": "Node-1-1", "isParent": false, "nodes": [ { "name": "Node-1-1-1", "isParent": false, "nodes": [ ], "connections": { "joins": [] } } ], "connections": { "joins": [ { "parent": "Node-1", "child": "Node-1-1" } ] } } ], "isParent": true } ]; function CheckConnections(){ var id=0; iterate(records, function (valid) { if(valid) { id = id + 1; console.log(id); } else alert("please define connections") } ); } function iterate(nodes,callback) { var connectionDefine = false; callback(false); } 
 <input type="button" value="Check Connections" onclick="CheckConnections()"> 

The following recursive solution will show you the error on the first missing connection relation encountered. I added comments so that you can track what happens.

It does not inspect all the connections: when it finds one that is properly made between child and parent, it breaks fast to move onto the next nodes.

Basically it consists in searching, for each child node, if the connections for the current parent/child relation are properly recorded. It should work with any number of child nodes / nested levels.

var records = [{"name":"Node-1","nodes":[{"name":"Node-1-1","isParent":false,"nodes":[{"name":"Node-1-1-1","isParent":false,"nodes":[],"connections":{"joins":[]}}], "connections":{"joins":[{"parent":"Node-1","child":"Node-1-1"}]}}],"isParent":true}];

function connections_control(records, parent = undefined) {
    // Browse the nodes list
    for (var node of records) {
        // Control if the keys we need do exist
        if (parent && node.connections && node.connections.joins) {
            var found = false;
            // Search in connections the current relation parent/child
            for (var connection of node.connections.joins) {
                if (connection.parent == parent && connection.child == node.name) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                // We checked all connections, but we did not find our current relation!
                console.log('Warning: Broken connection between parent node '+parent+' and child node '+node.name);
                break;
            }
        }
        if (node.nodes) {
            // The current node becomes parent, start again with the inner nodes list
            connections_control(node.nodes, node.name);
        }
    }
}

connections_control(records);

Note that on the first loop, which is taking your document at its root, there is no parent so there is no search for connections.

Execution:

nodejs childs.js
Warning: Broken connection between parent node Node-1-1 and child node Node-1-1-1

you can make a recursive function to do this, function takes two arguments-- node and its parent. At each recursion check if there are joins available and parent in joins is same as parent that was passed during recursion. And child in joins should be current node name. Something like this:

 var records = [ { "name": "Node-1", "nodes": [ { "name": "Node-1-1", "isParent": false, "nodes": [ { "name": "Node-1-1-1", "isParent": false, "nodes": [ ], "connections": { "joins": [] } } ], "connections": { "joins": [ { "parent": "Node-1", "child": "Node-1-1" } ] } } ], "isParent": true } ]; function CheckConnections(){ var id=0; var inValidNodes = []; records.forEach(function(node){ inValidNodes = checkValidConnections(node, null); if (inValidNodes.length > 0) return; }); if(inValidNodes.length === 0) { id = id + 1; console.log(id); } else { alert("please define connections " + inValidNodes); } } function checkValidConnections(node, parent){ var nodeName = node.name; if(!node.isParent){ var currentParentCondition = node.connections.joins.length > 0 && node.connections.joins[0].parent === parent && node.connections.joins[0].child === nodeName; if (!currentParentCondition) return [parent, nodeName]; } if (node.nodes.length > 0){ return checkValidConnections(node.nodes[0], nodeName); } else{ return []; } } 
 <input type="button" value="Check Connections" onclick="CheckConnections()"> 

You could use a recursive approach for calling check with an array and the parent name.

Inside, the first object of connections.joins is tested.

The result is either undefined , which means all connection are defined, or you get an object with the first missing connection.

The check takes the parent name from the calling object.

(With this, a check like !o.isParent ... could be omitted and just a check for parent could be used instead, because in the first call parent is undefined, which would prevent checking.)

 function check(array, parent) { var missing; array.some(function (o) { var j = o.connections && o.connections.joins && o.connections.joins[0]; if (!o.isParent && (!j || j.parent !== parent || j.child !== o.name)) { return missing = { parent: parent, child: o.name }; } if (o.nodes) { return missing = check(o.nodes, o.name); } }); return missing; } var records0 = [{ name: "Node-1", nodes: [{ name: "Node-1-1", isParent: false, nodes: [{ name: "Node-1-1-1", isParent: false, nodes: [], connections: { joins: [{ parent: "Node-1-1", child: "Node-1-1-1" }] } }], connections: { joins: [{ parent: "Node-1", child: "Node-1-1" }] } }], isParent: true }], records1 = [{ name: "Node-1", nodes: [{ name: "Node-1-1", isParent: false, nodes: [{ name: "Node-1-1-1", isParent: false, nodes: [], connections: { joins: [ /* missing */ ] } }], connections: { joins: [{ parent: "Node-1", child: "Node-1-1" }] } }], isParent: true }]; console.log(check(records0)); // undefined, nothing missing console.log(check(records1)); // missing { parent: "Node-1-1", child: "Node-1-1-1" } 

A slightly better data structure would help, if connections.joins is just an object and not an array, which needs iteration to check if the given parent/child match.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM