Recursive function creating too many copies of child nodes - javascript

I'm attempting to write a function to recursively delete nodes based on Parent-child relationships.
function recursiveDelete(parentNode, deleteStack) {
let toDelete = allNodes.filter(function (node) {
return node.Parent !== undefined && node.Parent[0] === parentNode.ID;
})
toDelete.forEach((childNode) => {
deleteStack.push(...recursiveDelete(childNode, toDelete));
});
return deleteStack;
}
When I run this code, it create arrays with multiple copies of each node to be deleted, which seems to correspond to the height of the tree. It still seems to be running in polynomial time, but it isn't ideal.
edit - below is an example of what gets returned when I run the function on allNodes, with the duplicates.
[
{
"ID": "recymaQKcdrGzAqRM",
"Name": "Depth 1",
"Type": "task",
"Duration": 0.1,
"Priority": "6",
"Parent": [
"recQT9BPQtqs7Cg0U"
],
"Predecessors": [
"recKwlRnVhKik3SZF"
],
"depth": 2
},
{
"ID": "recRcn1t2Nkupcb9L",
"Name": "Start",
"Type": "start",
"Duration": 0.1,
"Priority": "5",
"Parent": [
"recymaQKcdrGzAqRM"
]
},
{
"ID": "recBmEBC1bo1CcJ8i",
"Name": "Depth 2",
"Type": "task",
"Duration": 0.1,
"Priority": "5",
"Parent": [
"recymaQKcdrGzAqRM"
],
"Predecessors": [
"recRcn1t2Nkupcb9L"
]
},
{
"ID": "recRcn1t2Nkupcb9L",
"Name": "Start",
"Type": "start",
"Duration": 0.1,
"Priority": "5",
"Parent": [
"recymaQKcdrGzAqRM"
]
},
{
"ID": "recBmEBC1bo1CcJ8i",
"Name": "Depth 2",
"Type": "task",
"Duration": 0.1,
"Priority": "5",
"Parent": [
"recymaQKcdrGzAqRM"
],
"Predecessors": [
"recRcn1t2Nkupcb9L"
]
},
{
"ID": "rec7qUgu7kpnQ06s7",
"Name": "Start",
"Type": "start",
"Duration": 0.1,
"Priority": "5",
"Parent": [
"recBmEBC1bo1CcJ8i"
]
},
{
"ID": "rec5Lyx3zuAsCPv9W",
"Name": "Depth 3",
"Type": "task",
"Duration": 0.1,
"Priority": "5",
"Parent": [
"recBmEBC1bo1CcJ8i"
],
"Predecessors": [
"rec7qUgu7kpnQ06s7"
]
},
{
"ID": "rec7qUgu7kpnQ06s7",
"Name": "Start",
"Type": "start",
"Duration": 0.1,
"Priority": "5",
"Parent": [
"recBmEBC1bo1CcJ8i"
]
},
{
"ID": "rec5Lyx3zuAsCPv9W",
"Name": "Depth 3",
"Type": "task",
"Duration": 0.1,
"Priority": "5",
"Parent": [
"recBmEBC1bo1CcJ8i"
],
"Predecessors": [
"rec7qUgu7kpnQ06s7"
]
}
]
My current hack is to just remove duplicates:
[...new Set(recursiveDelete(allNode, [allNode]))]
But I'd like to figure out what I'm doing wrong. Thanks!
edit, I think I figured it out. Instead of passing toDelete to the recursive function, I should've only been passing [childNode], so the correct code looks like this:
function recursiveDelete(parentNode, deleteStack) {
let toDelete = allNodes.filter(function (node) {
return node.Parent !== undefined && node.Parent[0] === parentNode.ID;
});
toDelete.forEach((childNode) => {
deleteStack.push(...recursiveDelete(childNode, [childNode]));
});
return deleteStack;
}

Related

Any nice way to groupBy while transforming values with lodash

I am inexperienced with lodash, but I believe it can help me transform data into a desired format. I have tried varying level of methods described in the documentation, but I can not wrap my head around everything. I've looked here on SO, a few blogs, and the documentation. I have tried combining groupby and map, but I was unable to resolve the issue. I was also unsure how to log the steps.
Given an array of objects like this:
[
{
"parent": "app",
"value": "id"
"label": "1",
},
{
"parent": "app",
"value": "title"
"label": "Page",
},
{
"parent": "app",
"value": "description"
"label": "Desc page",
},
{
"parent": "home",
"value": "id"
"label": "2",
},
{
"parent": "home",
"value": "title"
"label": "Home",
},
{
"parent": "home",
"value": "description"
"label": "Desc home",
}
]
I would like to convert it to this:
{
"app": {
"id": "1",
"title": "Page",
"description": "Desc page"
},
"home": {
"id": "2",
"title": "Home",
"description": "Desc home"
}
}
Can anyone point me in the right direction?
You don't need lodash to accomplish such behavior. You can easily do this with a reduce.
const values = [
{
"parent": "app",
"value": "id",
"label": "1",
},
{
"parent": "app",
"value": "title",
"label": "Page",
},
{
"parent": "app",
"value": "description",
"label": "Desc page",
},
{
"parent": "home",
"value": "id",
"label": "2",
},
{
"parent": "home",
"value": "title",
"label": "Home",
},
{
"parent": "home",
"value": "description",
"label": "Desc home",
}
];
const mappedValues = values.reduce((acc, val) => {
acc[val.parent] = acc[val.parent] || {};
acc[val.parent][val.value] = val.label;
return acc;
}, {});
console.log(mappedValues);

Sorting Node's on the base of parent-Id [duplicate]

This question already has answers here:
Sort array of objects by string property value
(57 answers)
Closed 2 years ago.
Want to sort my data all node come first before calling its parent node
[
{
"id": 7832454551,
"name": "usr",
"type": "DIRECTORY"
},
{
"id": 7832454554,
"name": "applications",
"type": "DIRECTORY",
"parentId": 7832454553
},
{
"id": 7832454555,
"name": "mimeinfo.cache",
"type": "FILE",
"parentId": 7832454554
},
{
"id": 7832454553,
"name": "share",
"type": "DIRECTORY",
"parentId": 7832454552
},
{
"id": 7832454552,
"name": "local",
"type": "DIRECTORY",
"parentId": 7832454551
}
]
want to update data like this using javascript
[
{
"id": 7832454551,
"name": "usr",
"type": "DIRECTORY"
},
{
"id": 7832454552,
"name": "local",
"type": "DIRECTORY",
"parentId": 7832454551
},
{
"id": 7832454553,
"name": "share",
"type": "DIRECTORY",
"parentId": 7832454552
},
{
"id": 7832454554,
"name": "applications",
"type": "DIRECTORY",
"parentId": 7832454553
},
{
"id": 7832454555,
"name": "mimeinfo.cache",
"type": "FILE",
"parentId": 7832454554
}
]
try this one
const sortedData = [
{
"id": 7832454551,
"name": "usr",
"type": "DIRECTORY"
},
{
"id": 7832454554,
"name": "applications",
"type": "DIRECTORY",
"parentId": 7832454553
},
{
"id": 7832454555,
"name": "mimeinfo.cache",
"type": "FILE",
"parentId": 7832454554
},
{
"id": 7832454553,
"name": "share",
"type": "DIRECTORY",
"parentId": 7832454552
},
{
"id": 7832454552,
"name": "local",
"type": "DIRECTORY",
"parentId": 7832454551
}
].sort(function(a,b){
if(a.parentId!= undefined && b.parentId != undefined){
return a.parentId > b.parentId
}
return false;
});
console.log(sortedData);

Map the name of nodes onto links

This is my data and I am trying to map the name of the nodes to the sources and targets of the links.
var x = {
"nodes": [
{
"name": "Decision 3a"
},
{
"name": "Req 1"
},
{
"name": "Req 3c"
},
{
"name": "Cloud Services"
}
],
"links": [
{
"source": "0",
"target": "3",
"value": 100
},
{
"source": "4",
"target": "2",
"value": 100
}
]
};
I want the object to look like this for my visualization--
var x = {
"nodes": [
{
"name": "Decision 3a"
},
{
"name": "Req 3"
},
{
"name": "Req 3c"
},
{
"name": "Req 3b"
}
],
"links": [
{
"source": "Decision 3a",
"target": "Req 3c",
"value": 100
},
{
"source": "Cloud Services",
"target": "Req 1",
"value": 100
}
]
};
I tried adding the id to the nodes and then map them but in that case the id remain there in the nodes object.
you need to loop through the each object in the links array and get the index from the nodes array and assign that value to the links array.
i hope the below code solves the issue
var x = {
"nodes": [
{
"name": "Decision 3a"
},
{
"name": "Req 1"
},
{
"name": "Req 3c"
},
{
"name": "Req 4"
},
{
"name": "Cloud Services"
}
],
"links": [
{
"source": "0",
"target": "3",
"value": 100
},
{
"source": "4",
"target": "2",
"value": 100
}
]
};
x.links.forEach(o => {
let name = x.nodes[parseInt(o.source)].name;
o["source"] = name;
})
console.log("output",x)

Javascript sum of items in a complex object

I have some data that I'm counting and putting the totals into an array.
Here is the data and code:
var data = {
"cars": [
{
"id": "1",
"name": "name 1",
"thsub": [
{
"id": "11",
"name": "sub 1",
"stats": {
"items": 5,
},
"ions": null
},
{
"id": "22",
"name": "sub 2",
"stats": {
"items": 5,
},
"translations": null
}
],
"image": null
},
{
"id": "2",
"name": "name 2",
"thsub": [
{
"id": "33",
"name": "sub 43",
"stats": {
"items": 20,
},
"ions": null
},
{
"id": "44",
"name": "sub 76",
"stats": {
"items": 5,
},
"translations": null
}
],
"image": null
}
]
}
var thCount = [];
for(key in data.cars[0].thsub ){
if(data.cars[0].thsub[key].stats){
thCount.push(data.cars[0].thsub[key].stats.items);
}
}
console.log(thCount);
For some reason "thCount" is returning [5, 5] when the result should be: [10, 25]
where is the code going wrong?
The correct code for your problem is as pasted below:
**var count = [];
for(var i = 0; i < data.cars.length; i++){
countSum = 0;
for(key in data.cars[i].thsub){
countSum = countSum + data.cars[i].thsub[key].stats.items;
}
count.push(countSum);
}**
Try this code, will solve your problem.
You need another loop on cars.
var data = {
"cars": [{
"id": "1",
"name": "name 1",
"thsub": [{
"id": "11",
"name": "sub 1",
"stats": {
"items": 5,
},
"ions": null
}, {
"id": "22",
"name": "sub 2",
"stats": {
"items": 5,
},
"translations": null
}],
"image": null
},
{
"id": "2",
"name": "name 2",
"thsub": [{
"id": "33",
"name": "sub 43",
"stats": {
"items": 20,
},
"ions": null
}, {
"id": "44",
"name": "sub 76",
"stats": {
"items": 5,
},
"translations": null
}],
"image": null
}
]
}
var thCount = [];
for (var l = 0, m = data.cars.length; l < m; l++) {
thCount[l] = 0;
for (var i = 0, j = data.cars[l].thsub.length; i < j; i++) {
if (data.cars[l].thsub[i].stats) {
thCount[l]+=data.cars[l].thsub[i].stats.items;
}
}
}
console.log(thCount);
You should use reduce() and map() methods.Any of this using a callback function.
The reduce() method applies a function against an accumulator and each
value of the array (from left-to-right) to reduce it to a single
value.
The map() method creates a new array with the results of calling a
provided function on every element in this array.
var result=data.cars.map(function(item){
return item.thsub.reduce(function(a, b) { return a.stats.items + b.stats.items; });
});
var data = {
"cars": [
{
"id": "1",
"name": "name 1",
"thsub": [
{
"id": "11",
"name": "sub 1",
"stats": {
"items": 5,
},
"ions": null
},
{
"id": "22",
"name": "sub 2",
"stats": {
"items": 5,
},
"translations": null
}
],
"image": null
},
{
"id": "2",
"name": "name 2",
"thsub": [
{
"id": "33",
"name": "sub 43",
"stats": {
"items": 20,
},
"ions": null
},
{
"id": "44",
"name": "sub 76",
"stats": {
"items": 5,
},
"translations": null
}
],
"image": null
}
]
}
console.log(data.cars.map(function(item){
return item.thsub.reduce(function(a, b) { return a.stats.items + b.stats.items; });
}));

How can I group data with an Angular filter by timestamp?

My MVC return this JSON
[
{
"$id":"1",
"Tags":
[
{"$id":"2","Values":
[
{"$id":"3","Tag":{"$ref":"2"},"ID":4,"TagID":1,"Value1":5.00,"TimeStamp":"2015-10-26T15:23:50","Quality":1,"Tags_ID":1},
{"$id":"4","Tag":{"$ref":"2"},"ID":7,"TagID":1,"Value1":4.00,"TimeStamp":"2015-10-26T15:25:50","Quality":2,"Tags_ID":1}
],"Reports":[{"$ref":"1"}],"ID":1,"Name":"0101WT370/WT.VALUE","Type":null,"Archive":null,"Server":null,"Created":null,"Edited":null},
{"$id":"5","Values":[],"Reports":[{"$ref":"1"}],"ID":2,"Name":"0101WT371/WT.VALUE","Type":null,"Archive":null,"Server":null,"Created":null,"Edited":null},
{"$id":"6","Values":[],"Reports":[{"$ref":"1"}],"ID":3,"Name":"0101WT395/WT.VALUE","Type":null,"Archive":null,"Server":null,"Created":null,"Edited":null},
{"$id":"7","Values":[],"Reports":[{"$ref":"1"}],"ID":4,"Name":"0101WT396/WT.VALUE","Type":null,"Archive":null,"Server":null,"Created":null,"Edited":null}
],
"ID":3,"Name":"A"
},
{
"$id":"8",
"Tags":[],"ID":4,"Name":"B"
}
]
And i want winth Angular to group values by Timestamp part - hourly, daily or monthly
I want this result example for daily:
Tag | Timestamp | Value |
Tag1| 26-10-2015 | 4.5 = (9/2) = value1+value2 / count
Can you give me any suggestion?
EDIT:
I found this where give me something like way to start from :)
Try the code below :
JAVASCRIPT
function sortTimeStamp(obj) {
for(i=0; i<obj.length;i++) {
for(z=0; z<obj[i].Tags.length;z++) {
for(y=0; y<obj[i].Tags[z].Values.length;y++) {
obj[i].Tags[z].Values.sort(function (a, b) {
return new Date(b.TimeStamp).getTime() - new Date(a.TimeStamp).getTime();
});
}
}
}
return obj;
}
var myObj = [
{
"$id": "1",
"Tags": [
{
"$id": "2",
"Values": [
{
"$id": "3",
"Tag": {
"$ref": "2"
},
"ID": 4,
"TagID": 1,
"Value1": 5,
"TimeStamp": "2015-10-26T15:23:50",
"Quality": 1,
"Tags_ID": 1
},
{
"$id": "4",
"Tag": {
"$ref": "2"
},
"ID": 7,
"TagID": 1,
"Value1": 4,
"TimeStamp": "2015-10-26T15:25:50",
"Quality": 2,
"Tags_ID": 1
}
],
"Reports": [
{
"$ref": "1"
}
],
"ID": 1,
"Name": "0101WT370/WT.VALUE",
"Type": null,
"Archive": null,
"Server": null,
"Created": null,
"Edited": null
},
{
"$id": "5",
"Values": [],
"Reports": [
{
"$ref": "1"
}
],
"ID": 2,
"Name": "0101WT371/WT.VALUE",
"Type": null,
"Archive": null,
"Server": null,
"Created": null,
"Edited": null
},
{
"$id": "6",
"Values": [],
"Reports": [
{
"$ref": "1"
}
],
"ID": 3,
"Name": "0101WT395/WT.VALUE",
"Type": null,
"Archive": null,
"Server": null,
"Created": null,
"Edited": null
},
{
"$id": "7",
"Values": [],
"Reports": [
{
"$ref": "1"
}
],
"ID": 4,
"Name": "0101WT396/WT.VALUE",
"Type": null,
"Archive": null,
"Server": null,
"Created": null,
"Edited": null
}
],
"ID": 3,
"Name": "A"
},
{
"$id": "8",
"Tags": [],
"ID": 4,
"Name": "B"
}
];
myObj = sortTimeStamp(myObj);
console.log(myObj);
https://jsfiddle.net/3y7wfqwq/

Categories

Resources