Reputation: 6868
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(i.e 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()">
Upvotes: 3
Views: 975
Reputation: 4972
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
Upvotes: 2
Reputation: 386654
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.
Upvotes: 1
Reputation: 9808
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()">
Upvotes: 1