Related
I have a hierarchy tree JSON with multiple level of nesting. When i am trying to loop through the JSON for displaying tree structure in UI. I am ending up with cyclic redundancy since parent ID is same at different level. I need to add unique identifiers for parentID and ID, so in recursive call it does not end up in infinite loop.
Sample JSON :
[
{
"id": "12",
"text": "Man"
},
{
"id": "6",
"parentId": "12",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
},
{
"id": "7",
"parentId": "12",
"text": "Other"
},
{
"id": "6",
"parentId": "7",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
}
I have tried by adding depth to each level but not able to maintain the ParentId and Id relationship.
var depthArray = []
function addDepth(arr, depth = 0) {
arr.forEach(obj => {
obj.id = obj.id + '-' + depth;
if(obj.children !== undefined) {
addDepth(obj.children, depth + 1)
}})
return arr;
}
[
{
"id": "12",
"text": "Man"
},
{
"id": "6",
"parentId": "12",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
},
{
"id": "7",
"parentId": "12",
"text": "Other"
},
{
"id": "6-1",
"parentId": "7",
"text": "Boy"
},
{
"id": "9-1",
"parentId": "6-1",
"text": "Boy-Boy"
},
{
"id": "13-1",
"parentId": "9-1",
"text": "Boy-Boy-Boy"
}
]
Your recursion does not work, what about this ?
But not sure how to rename IDs:
'use strict';
function addDepth(arr, id, depth) {
if(depth === undefined) depth = 0;
if(id !== undefined)
arr.forEach(obj => {
if(id == obj.parentId) {
if(depth) obj.parentId += '-' + depth;
addDepth(arr, obj.id, depth + 1)
}
})
else arr.forEach(obj => { addDepth(arr, obj.id, depth); });
return arr;
}
console.log(addDepth(
[
{
"id": "12",
"text": "Man"
},
{
"id": "6",
"parentId": "12",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
},
{
"id": "7",
"parentId": "12",
"text": "Other"
},
{
"id": "6",
"parentId": "7",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
}
]
));
Hard to guess how structure may look like, but made a supposed output by hand and then similar code - looking up only (not sure how to distinguish same records with parentId difference):
12 Man
12 6 Man Boy
12 6 9 Man Boy Boy-Boy
12 6 9 13 Man Boy Boy-Boy Boy-Boy-Boy
12 7 Man Other
12 7 Man Other Boy
12 7 6 9 Man Other Boy Boy-Boy
12 7 6 9 13 Man Other Boy Boy-Boy Boy-Boy-Boy
var data = GetData();
var arr = [data[0].text], parent;
for(var i=0;i<data.length;i++) {
if(parent = data[i].parentId) {
arr.push(data[i].text); // we have parentId, so iterate back
for(var j=i;j >= 0;j--) {
if(data[j].id == parent) {
arr.push(data[j].text); // & colect text properties
if(data[j].parentId) {
parent = data[j].parentId;
j = i;
}
}
}
}
console.log(arr.reverse().join(" -> "));
arr = [];
}
function GetData() { return [
{
"id": "12",
"text": "Man"
},
{
"id": "6",
"parentId": "12",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
},
{
"id": "7",
"parentId": "12",
"text": "Other"
},
{
"id": "6",
"parentId": "7",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
}
];
}
This question already has answers here:
Finding the max value of an attribute in an array of objects
(21 answers)
Closed 5 years ago.
My Json data is as below
[{
"Name": "PieChart",
"Id": "1",
"ColumnLocation": "0",
"RowLocation": "0"
}, {
"Name": "Calendar",
"Id": "2",
"ColumnLocation": "1",
"RowLocation": "0"
}, {
"Name": "FavouriteFilter",
"Id": "3",
"ColumnLocation": "2",
"RowLocation": "0"
}, {
"Name": "FilterResults",
"Id": "4",
"ColumnLocation": "0",
"RowLocation": "1"
}, {
"Name": "Watched",
"Id": "5",
"ColumnLocation": "1",
"RowLocation": "1"
}]
I need to find the highest number of the ColumnLocation of the above data. I need that information because I can draw my dashboard based on this number of columns.
Reduce:
const a = [{
"Name": "PieChart",
"Id": "1",
"ColumnLocation": "0",
"RowLocation": "0"
}, {
"Name": "Calendar",
"Id": "2",
"ColumnLocation": "1",
"RowLocation": "0"
}, {
"Name": "FavouriteFilter",
"Id": "3",
"ColumnLocation": "2",
"RowLocation": "0"
}, {
"Name": "FilterResults",
"Id": "4",
"ColumnLocation": "0",
"RowLocation": "1"
}, {
"Name": "Watched",
"Id": "5",
"ColumnLocation": "1",
"RowLocation": "1"
}];
const r = a.reduce((a, c) => (c.ColumnLocation > a) ? c.ColumnLocation : a, 0);
console.log(r)
You could map every ColumnLocation key and use Math.max function to get the highest value.
var data = [{"Name":"PieChart","Id":"1","ColumnLocation":"0","RowLocation":"0"},{"Name":"Calendar","Id":"2","ColumnLocation":"1","RowLocation":"0"},{"Name":"FavouriteFilter","Id":"3","ColumnLocation":"2","RowLocation":"0"},{"Name":"FilterResults","Id":"4","ColumnLocation":"0","RowLocation":"1"},{"Name":"Watched","Id":"5","ColumnLocation":"1","RowLocation":"1"}],
res = data.map(v => v.ColumnLocation);
//console.log(Math.max.apply(Math, res));
console.log(Math.max(...res));
Chucking out there a solution using the lodash maxBy function:
const maxColumnLocation = _.maxBy(data, 'ColumnLocation').ColumnLocation;
I'm having a major brain fart. I have a java application that adds items to carts, and I'm using JSOUP to parse the html document since it can't run any javascript scripts. So I extracted this out of the getElementsByTag().html(); function. And now I need to find the value 1038, but while keeping in mind the values is not always 1038. So I would need it to search attribute -> 92 -> options -> id = 1038.
var spConfig = new Product.Config({
"attributes": {
"92": {
"id": "92",
"code": "color",
"label": "Color",
"options": [{
"id": "1038",
"label": "GREEN",
"price": "0",
"oldPrice": "0",
"products": ["94035", "94036", "94037", "94038", "94039", "94040", "94041", "94042", "94043", "94044"]
}]
},
"196": {
"id": "196",
"code": "size",
"label": "Size",
"options": [{
"id": "189",
"label": "8 ",
"price": "0",
"oldPrice": "0",
"products": ["94041"]
}, {
"id": "188",
"label": "8.5",
"price": "0",
"oldPrice": "0",
"products": ["94042"]
}, {
"id": "187",
"label": "9",
"price": "0",
"oldPrice": "0",
"products": ["94043"]
}, {
"id": "186",
"label": "9.5",
"price": "0",
"oldPrice": "0",
"products": ["94044"]
}, {
"id": "185",
"label": "10",
"price": "0",
"oldPrice": "0",
"products": ["94035"]
}, {
"id": "184",
"label": "10.5",
"price": "0",
"oldPrice": "0",
"products": ["94036"]
}, {
"id": "183",
"label": "11",
"price": "0",
"oldPrice": "0",
"products": ["94037"]
}, {
"id": "182",
"label": "11.5",
"price": "0",
"oldPrice": "0",
"products": ["94038"]
}, {
"id": "181",
"label": "12",
"price": "0",
"oldPrice": "0",
"products": ["94039"]
}, {
"id": "179",
"label": "13",
"price": "0",
"oldPrice": "0",
"products": ["94040"]
}]
}
},
"template": "$#{price}",
"basePrice": "129.98",
"oldPrice": "180",
"productId": "94013",
"chooseText": "Choose an Option...",
"taxConfig": {
"includeTax": false,
"showIncludeTax": false,
"showBothPrices": false,
"defaultTax": 0,
"currentTax": 0,
"inclTaxTitle": "Incl. Tax"
}
});
I need to receive the value "1038", but it can't just be a search function for integer 1038, because that value can possibly change in my script.
I am using angular JS and one of their examples:http://jsfiddle.net/furf/EJGHX/
I need to take the data when the update function occurs and add some values to it before I send to the server. (If doing this with angular instead of js would be better let me know)
I'm trying to get the 'parentid' and the 'index' and update the children.
Here is the data I'm looping through
{
"children": [{
"id": "5",
"parentid": "0",
"text": "Device Guides",
"index": "1",
"children": [{
"id": "10",
"index": "0",
"text": "Grandstream GXP-21XX"
}, {
"id": "11",
"index": "1",
"text": "Polycom Soundstation/Soundpoint"
}, {
"id": "23",
"index": "2",
"text": "New Polycom"
}]
}, {
"id": "6",
"parentid": "0",
"text": "Pre-Sales Evaluation",
"index": "0",
"children": []
}, {
"id": "7",
"parentid": "0",
"text": "Router Setup Guides",
"index": "2",
"children": [{
"id": "9",
"index": "0",
"text": "Sonicwall"
}, {
"id": "12",
"index": "1",
"text": "Cisco"
}]
}, {
"id": "9",
"parentid": "7",
"text": "Sonicwall",
"index": "0",
"children": []
}, {
"id": "10",
"parentid": "5",
"text": "Grandstream GXP-21XX",
"index": "0",
"children": []
}, {
"id": "11",
"parentid": "5",
"text": "Polycom Soundstation/Soundpoint",
"index": "1",
"children": []
}, {
"id": "12",
"parentid": "7",
"text": "Cisco",
"index": "1",
"children": []
}, {
"id": "15",
"parentid": "0",
"text": "Post-Sales Implementation Check List",
"index": "7",
"children": [{
"id": "16",
"index": "0",
"text": "Porting and New Number Details"
}, {
"id": "18",
"index": "1",
"text": "Partner Setup"
}, {
"id": "19",
"index": "2",
"text": "test"
}, {
"id": "21",
"index": "3",
"text": "test"
}]
}, {
"id": "16",
"parentid": "15",
"text": "Porting and New Number Details",
"index": "0",
"children": []
}, {
"id": "18",
"parentid": "15",
"text": "Partner Setup",
"index": "1",
"children": []
}, {
"id": "19",
"parentid": "15",
"text": "test",
"index": "2",
"children": []
}, {
"id": "20",
"parentid": "0",
"text": "test",
"index": "11",
"children": []
}, {
"id": "21",
"parentid": "15",
"text": "test",
"index": "3",
"children": []
}, {
"id": "23",
"parentid": "5",
"text": "New Polycom",
"index": "2",
"children": []
}, {
"id": "24",
"parentid": "0",
"text": "Test Markup",
"index": "14",
"children": []
}, {
"id": "25",
"parentid": "0",
"text": "test",
"index": "15",
"children": []
}]
}
This is how I'm currently looping through it, but it only gets the first dimension
for (i = 0, l = data.length; i < l; i++) {
parentid = data[i].id == null ? '0' : data[i].id;
data[i].index = i;
if (data[i].children) {
if (data[i].children.length > 0) {
for (q = 0, r = data[i].children.length; q < r; q++) {
data[i].children[q].parentid = parentid;
data[i].children[q].index = q;
}
}
}
}
I found this one on another fiddle, but I don't know how I would grab the parentid or the index
$.each(target.children, function(key, val) { recursiveFunction(key, val) });
function recursiveFunction(key, val) {
actualFunction(key, val);
var value = val['children'];
if (value instanceof Object) {
$.each(value, function(key, val) {
recursiveFunction(key, val)
});
}
}
function actualFunction(key, val) {}
If I'm understanding you correctly, you want each 'child' to have a parentID (defined by its parent; 0 otherwise) and an index (based on its position within it sibling set).
function normalize(parent) {
if (parent && parent.children) {
for (var i = 0, l = parent.children.length; i < l; ++i) {
var child = parent.children[i];
child.index = i;
if (!child.parentId) child.parentId = parent.id || '0';
normalize(child);
}
}
}
normalize(data);
Recursion is calling function inside the same function. Your sample is not a recursion at all;
function runRecursive(input) {
for (var i = 0, l = input.length; i < l; i++) {
var current = input[i];
parentid = current.id == null ? '0' : current.id;
current.index = i;
if (current.children && current.children.length > 0) {
runRecursive(current.children);
};
};
};
runRecursive(data.children);
Also you should define i and l with var keyword, otherwise it will be located in window context and recursion logic will broken.
Though I don't get what is parentid variable for and why it defined outside visible code.
I grab a list of data from the server and I have to convert it.
Part of this is turning it into a 3 dimensional array. After the "myArr[i].children.push(temp);" it leaves copies of the objects that were pushed in the root of the array. Can I either push without copying or how would I delete these? (I have underscore js included, I know they have good array functions :))
for (var i = 0; i < myArr.length; i++) {
myArr[i].children = [];
for (var q = 0; q < myArr.length; q++) {
if (myArr[i].id == myArr[q].parentid) {
var temp = {
id: myArr[q].id,
index: myArr[q].index,
text: myArr[q].text
}
myArr[i].children.push(temp);
};
};
};
The Data
[{
"id": "5",
"parentid": "0",
"text": "Device Guides",
"index": "0"
}, {
"id": "6",
"parentid": "0",
"text": "Pre-Sales Evaluation",
"index": "1"
}, {
"id": "7",
"parentid": "0",
"text": "Router Setup Guides",
"index": "2"
}, {
"id": "9",
"parentid": "7",
"text": "Sonicwall",
"index": "0"
}, {
"id": "10",
"parentid": "5",
"text": "Grandstream GXP-21XX",
"index": "1"
}, {
"id": "11",
"parentid": "5",
"text": "Polycom Soundstation\/Soundpoint",
"index": "2"
}, {
"id": "12",
"parentid": "7",
"text": "Cisco",
"index": "1"
}, {
"id": "15",
"parentid": "0",
"text": "Post-Sales Implementation Check List",
"index": "7"
}, {
"id": "16",
"parentid": "15",
"text": "Porting and New Number Details",
"index": "0"
}, {
"id": "18",
"parentid": "15",
"text": "Partner Setup",
"index": "1"
}, {
"id": "19",
"parentid": "15",
"text": "test",
"index": "2"
}, {
"id": "20",
"parentid": "0",
"text": "test",
"index": "11"
}, {
"id": "21",
"parentid": "15",
"text": "test",
"index": "3"
}, {
"id": "23",
"parentid": "5",
"text": "New Polycom",
"index": "0"
}, {
"id": "24",
"parentid": "0",
"text": "Test Markup",
"index": "14"
}, {
"id": "25",
"parentid": "0",
"text": "test",
"index": "15"
}]
After it is formated:
{
"children": [{
"id": "5",
"parentid": "0",
"text": "Device Guides",
"index": "1",
"children": [{
"id": "10",
"index": "0",
"text": "Grandstream GXP-21XX"
}, {
"id": "11",
"index": "1",
"text": "Polycom Soundstation/Soundpoint"
}, {
"id": "23",
"index": "2",
"text": "New Polycom"
}]
}, {
"id": "6",
"parentid": "0",
"text": "Pre-Sales Evaluation",
"index": "0",
"children": []
}, {
"id": "7",
"parentid": "0",
"text": "Router Setup Guides",
"index": "2",
"children": [{
"id": "9",
"index": "0",
"text": "Sonicwall"
}, {
"id": "12",
"index": "1",
"text": "Cisco"
}]
}, {
"id": "9",
"parentid": "7",
"text": "Sonicwall",
"index": "0",
"children": []
}, {
"id": "10",
"parentid": "5",
"text": "Grandstream GXP-21XX",
"index": "0",
"children": []
}, {
"id": "11",
"parentid": "5",
"text": "Polycom Soundstation/Soundpoint",
"index": "1",
"children": []
}, {
"id": "12",
"parentid": "7",
"text": "Cisco",
"index": "1",
"children": []
}, {
"id": "15",
"parentid": "0",
"text": "Post-Sales Implementation Check List",
"index": "7",
"children": [{
"id": "16",
"index": "0",
"text": "Porting and New Number Details"
}, {
"id": "18",
"index": "1",
"text": "Partner Setup"
}, {
"id": "19",
"index": "2",
"text": "test"
}, {
"id": "21",
"index": "3",
"text": "test"
}]
}, {
"id": "16",
"parentid": "15",
"text": "Porting and New Number Details",
"index": "0",
"children": []
}, {
"id": "18",
"parentid": "15",
"text": "Partner Setup",
"index": "1",
"children": []
}, {
"id": "19",
"parentid": "15",
"text": "test",
"index": "2",
"children": []
}, {
"id": "20",
"parentid": "0",
"text": "test",
"index": "11",
"children": []
}, {
"id": "21",
"parentid": "15",
"text": "test",
"index": "3",
"children": []
}, {
"id": "23",
"parentid": "5",
"text": "New Polycom",
"index": "2",
"children": []
}, {
"id": "24",
"parentid": "0",
"text": "Test Markup",
"index": "14",
"children": []
}, {
"id": "25",
"parentid": "0",
"text": "test",
"index": "15",
"children": []
}]
}
Here you go
tree = {0: {children: []}}
data.forEach(function(x) {
x.children = tree[x.id] ? tree[x.id].children : [];
tree[x.id] = x;
if(!tree[x.parentid])
tree[x.parentid] = {children: []}
tree[x.parentid].children.push(x)
})
result = tree[0].children
This solution is linear (iterates over the array just once) and doesn't require any pre-sorting.
http://jsfiddle.net/U47WY/
and here's how to convert the tree back to the linear array:
function flatten(source) {
return source.reduce(function(a, x) {
var children = x.children;
delete x.children;
return a.concat([x], flatten(x.children))
}, []);
}
Following on from a friendly discussion in the comments :
var zeroObj = {"children":[]};
for (var i = 0; i < myArr.length; i++) {
if(myArr[i].parentid === 0) {
zeroObj.children.push(myArr[i]);
} else {
for (var q = 0; q < myArr.length; q++) {
if (myArr[i].parentid == myArr[q].id) {
myArr[q].children = myArr[q].children || [];
myArr[q].children.push(myArr[i]);
};
};
}
};