Related
I have two arrays one is selectedOption and another is defaultOption, if the selectedOption id is present in any of the defaultOption array option property then it will be replaced with the current one . For an example i have added the expected_output
How could i achieve the expected output
let selectedOption = [
{
"count": 12,
"id": "16",
},
{
"count": 3,
"id": "4",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
]
let defaultOption = [
{
"item_select": {
"value": "16",
},
"options": []
},
{
"item_select": {
"value": "4",
},
"options": [
{
"value": "4"
},
{
"value": "5"
},
{
"value": "6"
},
{
"value": "7"
}
]
},
{
"item_select": {
"value": "8",
},
"options": [
{
"value": "8"
},
{
"value": "9"
},
{
"value": "10"
},
{
"value": "11"
}
]
},
{
"item_select": {
"value": "12",
},
"options": [
{
"value": "12"
},
{
"value": "13"
},
{
"value": "14"
},
{
"value": "15"
}
]
}
]
What I have tried so far
let expected_output = []
selectedOption.forEach(current => {
isDefaultOptionMatched = defaultOption.find(defOpt => defOpt.options.some(opt => opt.value === current.id))
if(isDefaultOptionMatched?.options){
let allMatches = selectedOption.filter(selOpt => {
defaultOption.some(defOption => defOption.options.find(dop => dop.value === selOpt.id))
})
expected_output.push(allMatches[allMatches.length - 1])
}else{
expected_output.push(current)
}
})
What I am getting is 6 elements instead of 5, and its not right.
expected output what I am looking
Instead of 6 objects of expected_output array it will be 5 objects because the second last object id => 6 is part of defaultOption[1].options. The element which got removed is.
{
"count": 3,
"id": "4",
},
Which is part of defaultOption[1].options
expected_output = [
{
"count": 12,
"id": "16",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
]
Any help is appreciated
Here's a semi-hacky approach (I don't like bucketing the items and remembering the order to rebuild the array later) but it works
let selectedOption = [
{
"count": 12,
"id": "16",
},
{
"count": 3,
"id": "4",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
];
let defaultOption = [
{
"item_select": {
"value": "16",
},
"options": []
},
{
"item_select": {
"value": "4",
},
"options": [
{
"value": "4"
},
{
"value": "5"
},
{
"value": "6"
},
{
"value": "7"
}
]
},
{
"item_select": {
"value": "8",
},
"options": [
{
"value": "8"
},
{
"value": "9"
},
{
"value": "10"
},
{
"value": "11"
}
]
},
{
"item_select": {
"value": "12",
},
"options": [
{
"value": "12"
},
{
"value": "13"
},
{
"value": "14"
},
{
"value": "15"
}
]
}
];
const result =
selectedOption.reduce((acc, el, order) => {
// bucket each element based on where it's found in defaultOption
const def = defaultOption.find(el2 => el2.options.some(el3 => el3.value === el.id));
if (def) {
const defId = def.item_select.value;
acc[defId] = {...el, order};
} else {
acc[el.id] = {...el, order};
}
return acc;
}, {});
// fix the order and remove the order field
const finish = Object.values(result).sort((a, b) => a.order - b.order).map(({order, ...rest}) => rest);
console.log(finish);
let selectedOption = [
{
"count": 12,
"id": "16",
},
{
"count": 3,
"id": "4",
},
{
"count": 2,
"id": "8",
},
{
"count": 4,
"id": "15",
},
{
"count": 1,
"id": "6",
},
{
"count": 34,
"id": "19",
}
]
let defaultOption = [
{
"item_select": {
"value": "16",
},
"options": []
},
{
"item_select": {
"value": "4",
},
"options": [
{
"value": "4"
},
{
"value": "5"
},
{
"value": "6"
},
{
"value": "7"
}
]
},
{
"item_select": {
"value": "8",
},
"options": [
{
"value": "8"
},
{
"value": "9"
},
{
"value": "10"
},
{
"value": "11"
}
]
},
{
"item_select": {
"value": "12",
},
"options": [
{
"value": "12"
},
{
"value": "13"
},
{
"value": "14"
},
{
"value": "15"
}
]
}
]
let expected_output = []
defaultOption.forEach(defOption => {
let allMatches = selectedOption.filter(selOpt => defOption.options.find(dop => dop.value === selOpt.id))
if(allMatches.length > 0){
expected_output.push(allMatches[allMatches.length - 1])
}
})
selectedOption.forEach(selOpt => {
let isDefaultOptionMatched = defaultOption.find(defOpt => defOpt.options.some(opt => opt.value === selOpt.id))
if(!isDefaultOptionMatched){
expected_output.push(selOpt)
}
})
console.log(expected_output)
I have 2 arrays of objects. Seen below
var subs = new Array();
var list_items = new Array();
subs = [
{ "value": 3, "text": "Guyana" },
{ "value": 4, "text": "St Lucia" },
{ "value": 5, "text": "Suriname" },
{ "value": 6, "text": "Barbados" },
{ "value": 7, "text": "3rd Party" },
{ "value": 8, "text": "JDL" }
];
list_items = [
{ "Id": 168, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 3, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" },
{ "Id": 169, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 4, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" },
{ "Id": 170, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 6, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" },
{ "Id": 171, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 5, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" }
];
What I'm trying to do is filter the "Subs" array, where any objects in the "list_items" array with the attribute ("StageRecipNum" matching the Subs "value" and "Resent" = false) should be removed from "Subs".
Here is the code I have to try to do this.
for (var i = 0; i < subs.length; i++) {
for (var j = 0; j < list_items.length; j++) {
if (parseInt(subs[i].value) == parseInt(list_items[j].StageRecipNum) &&
list_items[j].Resent == false) {
var hold = parseInt(list_items[j].StageRecipNum);
subs = subs.filter(el => el.value !== hold);
console.log(subs);
}
}
}
Afterward I am taking the remaining "Subs" array items and putting it in a dropdownlist to display on a form. All that works, the issue I am having is that one of the items in the list_items array keeps returning in the dropdownlist when it's not supposed to be there.
In the java console of visual studio code using Quokka, I get the below
As you can see, number 6 which is Barbados is not supposed to be there. I can't figure out why it's there and all the rest that not supposed to be in the array are not there. Only the 3rd Party and JDL supposed to be on the list.
I need help. What did I do wrong?
You can apply filter with some on the second array by matching StageRecipNum with value and resent property to be false. and once found take negate of some. Something like this:
const subs = [ { "value": 3, "text": "Guyana" }, { "value": 4, "text": "St Lucia" }, { "value": 5, "text": "Suriname" }, { "value": 6, "text": "Barbados" }, { "value": 7, "text": "3rd Party" }, { "value": 8, "text": "JDL" } ];
const list_items = [ { "Id": 168, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 3, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" }, { "Id": 169, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 4, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" }, { "Id": 170, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 6, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" }, { "Id": 171, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 5, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" } ];
const result = subs.filter(a=>!list_items.some(b=>b.StageRecipNum===a.value && b.Resent===false));
console.log(result);
You could take a Set and filter the array.
const
subs = [{ value: 3, text: "Guyana" }, { value: 4, text: "St Lucia" }, { value: 5, text: "Suriname" }, { value: 6, text: "Barbados" }, { value: 7, text: "3rd Party" }, { value: 8, text: "JDL" }],
list_items = [{ Id: 168, Month: "May", Resent: false, Stage: "2", StageRecipNum: 3, Title: "Demand_Forecast_2020_Month_May", parentID: "51" }, { Id: 169, Month: "May", Resent: false, Stage: "2", StageRecipNum: 4, Title: "Demand_Forecast_2020_Month_May", parentID: "51" }, { Id: 170, Month: "May", Resent: false, Stage: "2", StageRecipNum: 6, Title: "Demand_Forecast_2020_Month_May", parentID: "51" }, { Id: 171, Month: "May", Resent: false, Stage: "2", StageRecipNum: 5, Title: "Demand_Forecast_2020_Month_May", parentID: "51" }],
values = new Set(list_items.map(({ StageRecipNum }) => StageRecipNum)),
result = subs.filter(({ value }) => !values.has(value));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The problem arises because you are altering the array which you are looping over. The loop ends prematurely, because the length of the array is no longer the original length after removing items, resulting in not evaluating the remaining items.
To keep using the same code, keep updating a copy of the array while keeping the subs variable in its original state.
Below a less verbose way of achieving the same result. Filter the list_items for values where Resent is false and select its StageRecipNum. Next, filter the subs for values where the value is not contained by the list items:
var subs = [
{ "value": 3, "text": "Guyana" },
{ "value": 4, "text": "St Lucia" },
{ "value": 5, "text": "Suriname" },
{ "value": 6, "text": "Barbados" },
{ "value": 7, "text": "3rd Party" },
{ "value": 8, "text": "JDL" }
];
var list_items = [
{ "Id": 168, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 3, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" },
{ "Id": 169, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 4, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" },
{ "Id": 170, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 6, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" },
{ "Id": 171, "Month": "May", "Resent": false, "Stage": "2", "StageRecipNum": 5, "Title": "Demand_Forecast_2020_Month_May", "parentID": "51" }
];
var list_item_nums = list_items.filter(x => !x.Resent).map(x => x.StageRecipNum);
var filtered_subs = subs.filter(x => !list_item_nums.includes(x.value));
console.log(filtered_subs);
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"
}
];
}
I have a json like
var UserMatrix =[{
ID: 1,
Name: "Sid Edelmann",
UPI: 20483,
Guru: "Yes",
Views: {
February: 12,
March: 8,
April: 10,
May: 11,
June: 8
},
Ratings: {
February: 1,
March: 2,
April: 0,
May: 0,
June: 0
},
Comments: {
February: 1,
March: 1,
April: 0,
May: 0,
June: 1
},
TotalViews: {
FebJune: 49
},
TotalRatings: {
FebJune: 3
},
AverageRatings: {
FebJune: '#'
},
TotalComments: {
FebJune: 3
}
},
{
ID: 6,
Name: "Parthasarathy Perumbali",
UPI: "999999",
Guru: "",
Views: {
February: "8",
March: "5",
April: "4",
May: "1",
June: "8"
},
Ratings: {
February: "2",
March: "1",
April: "2",
May: "1",
June: "2"
},
Comments: {
February: "3",
March: "0",
April: "0",
May: "0",
June: "0"
},
TotalViews: {
FebJune: "26"
},
TotalRatings: {
FebJune: "8"
},
AverageRatings: {
FebJune: "#"
},
TotalComments: {
FebJune: "3"
}
}
];
I want to convert this json to the following. How can I do this?
var blogComments = [
{
"Name": "Sid Edelmann",
"Month": "Feb",
"Views": 12,
"Ratings": 1,
"Comments": 1
}, {
"Name": "Sid Edelmann",
"Month": "Mar",
"Views": 8,
"Ratings": 2,
"Comments": 1
},
{
"Name": "Sid Edelmann",
"Month": "Apr",
"Views": 10,
"Ratings": 0,
"Comments": 0
},
{
"Name": "Sid Edelmann",
"Month": "May",
"Views": 11,
"Ratings": 0,
"Comments": 0
},
{
"Name": "Sid Edelmann",
"Month": "Jun",
"Views": 8,
"Ratings": 0,
"Comments": 1
},
{
"Name": "Parthasarathy Perumbali",
"Month": "Feb",
"Views": 8,
"Ratings": 2,
"Comments": 3
},
{
"Name": "Parthasarathy Perumbali",
"Month": "Mar",
"Views": 5,
"Ratings": 1,
"Comments": 0
},
{
"Name": "Parthasarathy Perumbali",
"Month": "Apr",
"Views": 4,
"Ratings": 2,
"Comments": 0
},
{
"Name": "Parthasarathy Perumbali",
"Month": "May",
"Views": 1,
"Ratings": 1,
"Comments": 0
},
{
"Name": "Parthasarathy Perumbali",
"Month": "Jun",
"Views": 8,
"Ratings": 2,
"Comments": 0
}
];
I made following code to work without jQuery.
The code contains comments so it is pretty self-explanatory. As a special note, my code works even if you have different number of months for different matrix entries as long as Views, Ratings and Comments has same amount of months inside one entry. I wanted to make this to work like this, because it is less hard-coded way of doing things.
See Js fiddle example and remember to open your developer console to see the results.
The code is also here, below:
// UserMatrix data....
var UserMatrix =[{
ID: 1,
Name: "Sid Edelmann",
UPI: 20483,
Guru: "Yes",
Views: {
February: 12,
March: 8,
April: 10,
May: 11,
June: 8
},
Ratings: {
February: 1,
March: 2,
April: 0,
May: 0,
June: 0
},
Comments: {
February: 1,
March: 1,
April: 0,
May: 0,
June: 1
},
TotalViews: {
FebJune: 49
},
TotalRatings: {
FebJune: 3
},
AverageRatings: {
FebJune: '#'
},
TotalComments: {
FebJune: 3
}
},
{
ID: 6,
Name: "Parthasarathy Perumbali",
UPI: "999999",
Guru: "",
Views: {
February: "8",
March: "5",
April: "4",
May: "1",
June: "8"
},
Ratings: {
February: "2",
March: "1",
April: "2",
May: "1",
June: "2"
},
Comments: {
February: "3",
March: "0",
April: "0",
May: "0",
June: "0"
},
TotalViews: {
FebJune: "26"
},
TotalRatings: {
FebJune: "8"
},
AverageRatings: {
FebJune: "#"
},
TotalComments: {
FebJune: "3"
}
}
];
/**
* Yay! Method for converting UserMatrix to blogComments
*
*/
function convertUserMatrixToBlogComments() {
// Final format
var blogComments = [],
// Current matrix entry
userMatrix,
// Months
months = {};
// Loop each object in UserMatrix
for(var i=0; i < UserMatrix.length; i++) {
// Current
userMatrix = UserMatrix[i];
// Find out months
for (var m in userMatrix.Views) {
if(userMatrix.Views.hasOwnProperty(m)) {
// Makes container for months
// e.g. February: "Feb"
months[m] = m.substring(0, 3);
}
};
// Go through all matrix data for months and push to comments
for(var j in months) {
if(months.hasOwnProperty(j)) {
blogComments.push({
Name: userMatrix.Name,
Month: months[j],
Views: parseInt(userMatrix.Views[j], 10),
Ratings: parseInt(userMatrix.Ratings[j], 10),
Comments: parseInt(userMatrix.Comments[j], 10)
});
}
}
// Next cycle starts here..
months = {};
}
// We are done!
return blogComments;
}
// Lets do this!
var blogComments = convertUserMatrixToBlogComments();
// See the results
console.log(blogComments);
Here you go.
newUsers = [];
$.each(UserMatrix, function (i, user) {
$.each(user.Views, function(key, value){
newUser = {};
newUser['Name'] = user['Name'];
newUser['Month'] = key;
newUser['Views'] = value;
newUser['Ratings'] = user.Ratings[key];
newUser['Comments'] = user.Comments[key];
newUsers.push(newUser);
});
});
console.log(JSON.stringify(newUsers));
Demo: http://jsfiddle.net/robschmuecker/Bc4hw/
Outputs:
[{
"Name": "Sid Edelmann",
"Month": "February",
"Views": 12,
"Ratings": 1,
"Comments": 1
}, {
"Name": "Sid Edelmann",
"Month": "March",
"Views": 8,
"Ratings": 2,
"Comments": 1
}, {
"Name": "Sid Edelmann",
"Month": "April",
"Views": 10,
"Ratings": 0,
"Comments": 0
}, {
"Name": "Sid Edelmann",
"Month": "May",
"Views": 11,
"Ratings": 0,
"Comments": 0
}, {
"Name": "Sid Edelmann",
"Month": "June",
"Views": 8,
"Ratings": 0,
"Comments": 1
}, {
"Name": "Parthasarathy Perumbali",
"Month": "February",
"Views": "8",
"Ratings": "2",
"Comments": "3"
}, {
"Name": "Parthasarathy Perumbali",
"Month": "March",
"Views": "5",
"Ratings": "1",
"Comments": "0"
}, {
"Name": "Parthasarathy Perumbali",
"Month": "April",
"Views": "4",
"Ratings": "2",
"Comments": "0"
}, {
"Name": "Parthasarathy Perumbali",
"Month": "May",
"Views": "1",
"Ratings": "1",
"Comments": "0"
}, {
"Name": "Parthasarathy Perumbali",
"Month": "June",
"Views": "8",
"Ratings": "2",
"Comments": "0"
}]
This should work for you
var result = [];
UserMatrix.forEach(function (user) {
var allMonths = Object.keys(user.Views);
allMonths.forEach(function(month){
var monthObject = {};
monthObject["Name"] = user.Name;
monthObject["Month"] = month.slice(0,3);
monthObject["Views"] = user.Views[month];
monthObject["Ratings"] = user.Ratings[month];
monthObject["Comments"] = user.Comments[month];
result.push(monthObject);
});
})
console.log(result);
Fiddle
var finalArr = [];
var months = ["February", "March", "April", "May", "June"];
UserMatrix.forEach(function (user) {
months.forEach(function (m) {
finalArr.push({
Name: user.Name,
Month: m,
Views: user.Views[m],
Ratings: user.Ratings[m],
Comments: user.Comments[m]
});
});
});
document.getElementById('op').innerHTML = JSON.stringify(finalArr);
console.log(finalArr);
Update
Specifying the months and attributes within an array might give you more flexibility while enhancing your application.
Fiddle
var finalArr = [];
var months = ["February", "March", "April", "May", "June"];
var attr = ["Views", "Ratings", "Comments"];
UserMatrix.forEach(function (user) {
months.forEach(function (m) {
var newObj = {};
newObj.Name=user.Name;
newObj.Month = m;
attr.forEach(function (a) {
newObj[a]=user[a][m];
});
finalArr.push(newObj);
});
});
document.getElementById('op').innerHTML = JSON.stringify(finalArr);
console.log(JSON.stringify(finalArr));
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]);
};
};
}
};