I have a deeply nested array like below. I want to flat the structure.
data = [
{
"id": 4321,
"name": "category1",
"parentId": null,
"children": [
{
"id": 1234,
"name": "category1",
"parentId": 4321,
"children": [
{
"id": 8327548,
"name": "001",
"parentId": 1234
},
{
"id": 8327549,
"name": "002",
"parentId": 1234
},
]
},
{
"id": 6786,
"name": "Associations",
"parentId": 4321
},
{
"id": 8262439,
"name": "category1",
"parentId": 4321
},
{
"id": 8245,
"name": "Rights",
"parentId": 4321,
"children": [
{
"id": 2447,
"name": "Organizations",
"parentId": 8245
},
{
"id": 9525,
"name": "Services",
"parentId": 8245
},
{
"id": 8448,
"name": "Organizations",
"parentId": 8245
}
]
},
{
"id": 8262446,
"name": "Women's Rights",
"parentId": 4321
}
]
},
{
"id": 21610,
"name": "Agriculture",
"parentId": null,
"children": [
{
"id": 3302,
"name": "categoryABC",
"parentId": 21610,
"children": [
{
"id": 85379,
"name": "categoryABC - General",
"parentId": 3302
},
{
"id": 85380,
"name": "categoryABC Technology",
"parentId": 3302
}
]
},
{
"id": 8303,
"name": "Fungicides",
"parentId": 21610,
"children": [
{
"id": 8503,
"name": "Fungicides - General",
"parentId": 8303
}
]
},
]
},
];
Expected output
output = [
{
"id": 8327548,
"name": "001",
"parentId": 1234
},
{
"id": 8327549,
"name": "002",
"parentId": 1234
},
...OTHER OBJECTS....
]
What I have tried so far. This is not pushing the inner children items.
function flat(array) {
var result = [];
array.forEach(function (a) {
result.push(a);
if (Array.isArray(a.children)) {
result = result.concat(flat(a.children));
}
});
return result;
}
let results = flat(data)
console.log("test", results)
Stack Snippet:
const data = [
{
"id": 4321,
"name": "category1",
"parentId": null,
"children": [
{
"id": 1234,
"name": "category1",
"parentId": 4321,
"children": [
{
"id": 8327548,
"name": "001",
"parentId": 1234
},
{
"id": 8327549,
"name": "002",
"parentId": 1234
},
]
},
{
"id": 6786,
"name": "Associations",
"parentId": 4321
},
{
"id": 8262439,
"name": "category1",
"parentId": 4321
},
{
"id": 8245,
"name": "Rights",
"parentId": 4321,
"children": [
{
"id": 2447,
"name": "Organizations",
"parentId": 8245
},
{
"id": 9525,
"name": "Services",
"parentId": 8245
},
{
"id": 8448,
"name": "Organizations",
"parentId": 8245
}
]
},
{
"id": 8262446,
"name": "Women's Rights",
"parentId": 4321
}
]
},
{
"id": 21610,
"name": "Agriculture",
"parentId": null,
"children": [
{
"id": 3302,
"name": "categoryABC",
"parentId": 21610,
"children": [
{
"id": 85379,
"name": "categoryABC - General",
"parentId": 3302
},
{
"id": 85380,
"name": "categoryABC Technology",
"parentId": 3302
}
]
},
{
"id": 8303,
"name": "Fungicides",
"parentId": 21610,
"children": [
{
"id": 8503,
"name": "Fungicides - General",
"parentId": 8303
}
]
},
]
},
];
function flat(array) {
var result = [];
array.forEach(function (a) {
result.push(a);
if (Array.isArray(a.children)) {
result = result.concat(flat(a.children));
}
});
return result;
}
let results = flat(data)
console.log("test", results)
Can someone help me please?
I'd suggest a recursive approach, walking through the input structure and pushing each object found to the result array.
data = [ { "id": 4321, "name": "category1", "parentId": null, "children": [ { "id": 1234, "name": "category1", "parentId": 4321, "children": [ { "id": 8327548, "name": "001", "parentId": 1234 }, { "id": 8327549, "name": "002", "parentId": 1234 }, ] }, { "id": 6786, "name": "Associations", "parentId": 4321 }, { "id": 8262439, "name": "category1", "parentId": 4321 }, { "id": 8245, "name": "Rights", "parentId": 4321, "children": [ { "id": 2447, "name": "Organizations", "parentId": 8245 }, { "id": 9525, "name": "Services", "parentId": 8245 }, { "id": 8448, "name": "Organizations", "parentId": 8245 } ] }, { "id": 8262446, "name": "Women's Rights", "parentId": 4321 } ] }, { "id": 21610, "name": "Agriculture", "parentId": null, "children": [ { "id": 3302, "name": "categoryABC", "parentId": 21610, "children": [ { "id": 85379, "name": "categoryABC - General", "parentId": 3302 }, { "id": 85380, "name": "categoryABC Technology", "parentId": 3302 } ] }, { "id": 8303, "name": "Fungicides", "parentId": 21610, "children": [ { "id": 8503, "name": "Fungicides - General", "parentId": 8303 } ] }, ] }, ];
function flat(input, result = []) {
let newObj = null;
for(let k in input) {
if (typeof(input[k]) === 'object') {
flat(input[k], result);
} else {
if (!newObj) {
newObj = {};
result.push(newObj);
}
newObj[k] = input[k];
}
}
return result;
}
console.log(flat(data))
.as-console-wrapper { max-height: 100% !important; top: 0; }
You need to delete a.children from the original array:
if (Array.isArray(a.children)) {
result = result.concat(flat(a.children));
delete a.children;
}
(As #T.J.Crowde suggested, I left the snippet with a smaller array)
const data = [
{
"id": 4321,
"name": "category1",
"parentId": null,
"children": [
{
"id": 1234,
"name": "category1",
"parentId": 4321,
"children": [
{
"id": 8327548,
"name": "001",
"parentId": 1234
},
{
"id": 8327549,
"name": "002",
"parentId": 1234
},
]
},
]
},
];
function flat(array) {
var result = [];
array.forEach(function (a) {
result.push(a);
if (Array.isArray(a.children)) {
result = result.concat(flat(a.children));
delete a.children;
}
});
return result;
}
let results = flat(data)
console.log("test", results)
Related
I have below JSON for example where I need to extract all categories Id from the last subcategory if its not empty. For instance: On below JSON I need Ids like mens-apparel-ricky inside last categories object but if this categories was empty I like to extract the last ID like womens-new-arrivals. Basically it should be the list of all these ID's extracted.
Thanks in Advance
"categories": [{
"id": "featured",
"name": "NEW ARRIVALS",
"categories": [{
"id": "featured-new-arrivals",
"name": "New Arrivals",
"categories": [{
"id": "mens-new-arrivals",
"name": "Mens",
"categories": []
}, {
"id": "womens-new-arrivals",
"name": "Womens",
"categories": [{
"id": "mens-apparel-ricky",
"name": "Relaxed",
"categories": []
}, {
"id": "new-arrivals-kids",
"name": "Kids",
"categories": []
}, {
"id": "new-arrivals-accessories",
"name": "Accessories",
"categories": []
}]
}, {
"id": "collections",
"name": "Featured",
"categories": [{
"id": "spring-shop",
"name": "Spring Shop",
"categories": [{
"id": "spring-shop-mens",
"name": "Spring Shop Men's",
"categories": []
}, {
"id": "spring-shop-womens",
"name": "Spring Shop Women's",
"categories": []
}]
}, {
"id": "the-festival-shop",
"name": "The Festival Shop",
"categories": [{
"id": "mens-festival-shop",
"name": "Mens Festival Shop",
"categories": []
}, {
"id": "womens-festival-shop",
"name": "Womens Festival Shop",
"categories": []
}]
}, {
"id": "buddha-collections",
"name": "The Icons Shop",
"categories": [{
"id": "buddha-collections-men",
"name": "Mens",
"categories": []
}, {
"id": "buddha-collections-women",
"name": "Womens",
"categories": []
}]
}, {
"id": "all-black",
"name": "All Black Everything",
"categories": []
}]
}]
}, {
"id": "denim",
"name": "DENIM",
"categories": [{
"id": "denim-view-all",
"name": "Shop All Denim",
"categories": [{
"id": "denim-view-all-mens",
"name": "Mens Denim",
"categories": []
}, {
"id": "denim-view-all-womens",
"name": "Womens Denim",
"categories": []
}, {
"id": "denim-view-all-kids",
"name": "Kids Denim",
"categories": []
}]
}, {
"id": "denim-collections",
"name": "Featured",
"categories": [{
"id": "denim-collections-signature-stitch",
"name": "Big T & Super T Stitch",
"categories": []
}, {
"id": "denim-collections-lighten-up",
"name": "Light Wash Denim",
"categories": []
}, {
"id": "dark-wash-denim",
"name": "Dark Wash Denim",
"categories": []
}]
}]
}]
}
This is what I have tried but being new to coding getting difficult to get list form this complex structure.
var rootCategories = (jsonData.categories);
for (var i=0; i < rootCategories.length; i++)
{
var firstChild = (jsonData.categories[i].categories);
for (var j=0; j < firstChild.length; j++)
{
if ((firstChild[j].categories[j].length != 0)) {
catId = firstChild[j].categories[j].id
console.log(catId);
}
}
}
Below is one possible way to achieve the target.
Code Snippet
// recursive method to get "id"s
const getIds = arr => (
arr.flatMap( // iterate using ".flatMap()" to avoid nesting
({id, categories}) => { // de-structure to directly access "id" & "categories"
if ( // if "categories" is not empty, recurse to next level
Array.isArray(categories) &&
categories.length > 0
) {
return getIds(categories);
} else { // if it is empty, simply return the id
return id;
}
}
)
);
const rawData = {
"categories": [{
"id": "featured",
"name": "NEW ARRIVALS",
"categories": [{
"id": "featured-new-arrivals",
"name": "New Arrivals",
"categories": [{
"id": "mens-new-arrivals",
"name": "Mens",
"categories": []
}, {
"id": "womens-new-arrivals",
"name": "Womens",
"categories": [{
"id": "mens-apparel-ricky",
"name": "Relaxed",
"categories": []
}, {
"id": "new-arrivals-kids",
"name": "Kids",
"categories": []
}, {
"id": "new-arrivals-accessories",
"name": "Accessories",
"categories": []
}]
}, {
"id": "collections",
"name": "Featured",
"categories": [{
"id": "spring-shop",
"name": "Spring Shop",
"categories": [{
"id": "spring-shop-mens",
"name": "Spring Shop Men's",
"categories": []
}, {
"id": "spring-shop-womens",
"name": "Spring Shop Women's",
"categories": []
}]
}, {
"id": "the-festival-shop",
"name": "The Festival Shop",
"categories": [{
"id": "mens-festival-shop",
"name": "Mens Festival Shop",
"categories": []
}, {
"id": "womens-festival-shop",
"name": "Womens Festival Shop",
"categories": []
}]
}, {
"id": "buddha-collections",
"name": "The Icons Shop",
"categories": [{
"id": "buddha-collections-men",
"name": "Mens",
"categories": []
}, {
"id": "buddha-collections-women",
"name": "Womens",
"categories": []
}]
}, {
"id": "all-black",
"name": "All Black Everything",
"categories": []
}]
}]
}, {
"id": "denim",
"name": "DENIM",
"categories": [{
"id": "denim-view-all",
"name": "Shop All Denim",
"categories": [{
"id": "denim-view-all-mens",
"name": "Mens Denim",
"categories": []
}, {
"id": "denim-view-all-womens",
"name": "Womens Denim",
"categories": []
}, {
"id": "denim-view-all-kids",
"name": "Kids Denim",
"categories": []
}]
}, {
"id": "denim-collections",
"name": "Featured",
"categories": [{
"id": "denim-collections-signature-stitch",
"name": "Big T & Super T Stitch",
"categories": []
}, {
"id": "denim-collections-lighten-up",
"name": "Light Wash Denim",
"categories": []
}, {
"id": "dark-wash-denim",
"name": "Dark Wash Denim",
"categories": []
}]
}]
}]
}]
};
console.log(getIds(rawData.categories));
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added in the snippet above.
If you're not afraid of reference loops (shouldn't technically happen in a serialized REST response) you can try recurring function as the simplest way to achieve this
function getIDs(node, isRoot = false) {
if (!node.categories.length) // if I understood your question correctly, you don't want parents to be printed out, otherwise just check for isRoot instead
return isRoot || console.log(node.id);
// with above you won't access non-existent id of the root collection
// because it will stop checking after first true statement
for (const category of categories)
getIDs(category);
}
getIDs(collection, true);
BE Response:- which I am getting from Backend Service
{
"data": {
"type": "AnyType",
"resources": [
{
"id": 1,
"treeId": "1",
"name": "name1",
"description": "description1",
"children": [
{
"id": 3,
"treeId": "1-3",
"name": "subName1",
"description": "subDescription1",
"children": [
{
"id": 6,
"treeId": "1-3-6",
"name": "subSubName1",
"description": "subSubDesc1",
"children": []
}
]
}
]
},
{
"id": 2,
"treeId": "2",
"name": "name2",
"description": "description2",
"children": [
{
"id": 7,
"treeId": "2-7",
"name": "subName2",
"description": "subDescription2",
"children": []
}
]
}
]
}
}
But I need to modify this response to as below on FE
Expected Response:- means I need to join name and description field text to one(in name field ) as below:-
{
"data": {
"type": "AnyType",
"resources": [
{
"id": 1,
"treeId": "1",
"name": "name1-description1",
"description": "description1",
"children": [
{
"id": 3,
"treeId": "1-3",
"name": "subName1-subDescription1",
"description": "subDescription1",
"children": [
{
"id": 6,
"treeId": "1-3-6",
"name": "subSubName1-subSubDesc1",
"description": "subSubDesc1",
"children": []
}
]
}
]
},
{
"id": 2,
"treeId": "2",
"name": "name2-description2",
"description": "description2",
"children": [
{
"id": 7,
"treeId": "2-7",
"name": "subName2-subDescription2",
"description": "subDescription2",
"children": []
}
]
}
]
}
}
there could be n number of children of each object and children can have an array of objects.
What I have done:- I am able to change the very first name but not children name
let resDataArry = [];
let descData: DynamicResource;
response.forEach((x, index) => {
const descName = x.name + ' ' + x.description;
descData = { ...tree.resources[index], name: descName };
resDataArry.push(descData);
});
return resDataArry;
Please help.
You can use nested Array#forEach to access children array and then concatenate the name and description together.
let data = {
"data": {
"type": "AnyType",
"resources": [
{
"id": 1,
"treeId": "1",
"name": "name1",
"description": "description1",
"children": [
{
"id": 3,
"treeId": "1-3",
"name": "subName1",
"description": "subDescription1",
"children": [
{
"id": 6,
"treeId": "1-3-6",
"name": "subSubName1",
"description": "subSubDesc1",
"children": []
}
]
}
]
},
{
"id": 2,
"treeId": "2",
"name": "name2",
"description": "description2",
"children": [
{
"id": 7,
"treeId": "2-7",
"name": "subName2",
"description": "subDescription2",
"children": []
}
]
}
]
}
}
data.data.resources.forEach(function(item){
item.name = item.name + ' ' + item.description;
item.children.forEach(function(child){
child.name = child.name + ' ' + child.description;
});
});
console.log(data);
I'm trying to update the 'positionTitle' field of my graphData object with the 'positionTitle fields of my individualData array.
I need to do it accurately, both sets of data have 'accounts' which both have the same id and fullname for user, I was hoping to try and use this to do the matching.
I want the positionTitle's from the users with same account id or name (whichever is easier) to go into the objects fields.
This is currently what I have:
My Object (that i want to update):
graphData = {
"name": "Annual meetings",
"engagementAreas": [{
"id": "1",
"engagementTypes": [{
"name": "forestry",
"engagements": []
},
{
"name": "houses",
"engagements": [{
"name": "engagement1",
"members": [{
"id": "e334", "account": {
"id": "eefe", "fullName": "jim bean"
},
"position": {
"id": "3434",
"positionTitle": "Manager"
}
}]
}]
},
{
"name": "landscaping",
"engagements": [{
"name": "engagement1343",
"members": [{
"id": "e334", "account": {
"id": "123", "fullName": "john boer"
},
"position": {
"id": "4545",
"positionTitle": "Senior Manager"
}
}]
}]
}
]
},
{
"name": "community days",
"engagementTypes": [{
"name": "skyscraping",
"engagements": []
},
{
"name": "tennis",
"engagements": [{
"name": "engagement346",
"members": [{
"id": "34", "account": {
"id": "0010X000048DDMsQAO", "fullName": "edy long"
},
"position": {
"id": "3999434",
"positionTitle": "Ultime Manager"
}
}]
}]
},
{
"name": "Juicing",
"engagements": [{
"name": "347343",
"members": [{
"id": "4546", "account": {
"id": "001b000003WnPy1AAF", "fullName": "jeff bint"
},
"position": {
"id": "35006",
"positionTitle": "Senior Ultimate Manager"
}
}]
}]
}]
}]
}
My array whose positionTitles I want to take:
IndividualData = [{
"account": {
"id": "001b000003WnPy1AAF",
"fullName": "jeff bint"
},
"positions": [{
"id": "a16b0000004AxeBAAS",
"organizationId": "001b0000005gxmlAAA",
"organizationName": "a",
"positionTitle": "Senior Manager, Energy",
"positionLevel": "5-Middle Management & Advisers",
"isPrimary": true,
"startDate": "2016-10-07",
"endDate": null
}]
}, {
"account": {
"id": "0010X000048DDMsQAO",
"fullName": "edy long"
},
"positions": [{
"id": "a160X000004nKfhQAE",
"organizationId": "001b0000005gxmlAAA",
"organizationName": "a",
"positionTitle": "Managing Director",
"positionLevel": "4-Head of Business Unit/Head of Region",
"isPrimary": true,
"startDate": "2018-03-05",
"endDate": null
}]
}, {
"account": {
"id": "123",
"fullName": "john boer"
},
"positions": [{
"id": "325345634634",
"organizationId": "001b0000005gxmlAAA",
"organizationName": "a",
"positionTitle": "Managing Director",
"positionLevel": "4-Head of Business Unit/Head of Region",
"isPrimary": true,
"startDate": "2018-03-05",
"endDate": null
}]
}
]
The function I'm currently using, which does take the first positiontitle field of the array:
const updatedGraphTable = { ...graphData,
engagementAreas: graphData.engagementAreas.map(area => ({ ...area,
engagementTypes: area.engagementTypes.map(type => ({ ...type,
engagements: type.engagements.map(engagement => ({ ...engagement,
members: engagement.members.map(member => ({ ...member,
position: { ...member.position,
positionTitle: IndividualData[0].positions[0].positionTitle
}
}))
}))}))
}))
};
console.log(updatedGraphTable)
console.log('a' + JSON.stringify(updatedGraphTable))
my expected result with the positions updated:
updatedGraphData = {
"name": "Annual meetings",
"engagementAreas": [{
"id": "1",
"engagementTypes": [{
"name": "forestry",
"engagements": []
},
{
"name": "houses",
"engagements": [{
"name": "engagement1",
"members": [{
"id": "e334", "account": {
"id": "eefe", "fullName": "jim bean"
},
"position": {
"id": "3434",
"positionTitle": "Manager"
}
}]
}]
},
{
"name": "landscaping",
"engagements": [{
"name": "engagement1343",
"members": [{
"id": "e334", "account": {
"id": "123", "fullName": "john boer"
},
"position": {
"id": "4545",
"positionTitle": "Managing Director"
}
}]
}]
}
]
},
{
"name": "community days",
"engagementTypes": [{
"name": "skyscraping",
"engagements": []
},
{
"name": "tennis",
"engagements": [{
"name": "engagement346",
"members": [{
"id": "34", "account": {
"id": "0010X000048DDMsQAO", "fullName": "edy long"
},
"position": {
"id": "3999434",
"positionTitle": "Managing Director"
}
}]
}]
},
{
"name": "Juicing",
"engagements": [{
"name": "347343",
"members": [{
"id": "4546", "account": {
"id": "001b000003WnPy1AAF", "fullName": "jeff bint"
},
"position": {
"id": "35006",
"positionTitle": "Senior Manager, Energy"
}
}]
}]
}]
}]
}
My current result:
{
"name": "Annual meetings",
"engagementAreas": [{
"id": "1",
"engagementTypes": [{
"name": "forestry",
"engagements": []
}, {
"name": "houses",
"engagements": [{
"name": "engagement1",
"members": [{
"id": "e334",
"account": {
"id": "eefe"
},
"position": {
"id": "3434",
"positionTitle": "Senior Manager, Energy"
}
}]
}]
}, {
"name": "landscaping",
"engagements": [{
"name": "engagement1343",
"members": [{
"position": {
"id": "4545",
"positionTitle": "Senior Manager, Energy"
}
}]
}]
}]
}, {
"name": "community days",
"engagementTypes": [{
"name": "skyscraping",
"engagements": []
}, {
"name": "tennis",
"engagements": [{
"name": "engagement346",
"members": [{
"id": "34",
"account": {
"id": "3546"
},
"position": {
"id": "3999434",
"positionTitle": "Senior Manager, Energy"
}
}]
}]
}, {
"name": "Juicing",
"engagements": [{
"name": "347343",
"members": [{
"id": "4546",
"account": {
"id": "3545"
},
"position": {
"id": "35006",
"positionTitle": "Senior Manager, Energy"
}
}]
}]
}]
}]
}
Sure, the trick would be to first map your data into an object (so you don't have to search over both arrays all the time), and then conditionally set the value (as I saw that your first manager, doesn't really have a matching position).
So to create the dictionary for usage in your later model, you can first do
// first map the accountId to positions
const accountIdToPositionDict = individualData.reduce( (current, item) => {
current[item.account.id] = (item.positions.filter( position => position.isPrimary )[0] || {} ).positionTitle;
return current;
}, {} );
This would then have an object where accountIdToPositionDict["123"] would be Managing Director, and then change the duplicating logic into:
const updatedGraphTable = { ...graphData,
engagementAreas: graphData.engagementAreas.map(area => ({ ...area,
engagementTypes: area.engagementTypes.map(type => ({ ...type,
engagements: type.engagements.map(engagement => ({ ...engagement,
members: engagement.members.map(member => ({ ...member,
position: { ...member.position,
// use the found positionTitle, or the original one that was given
positionTitle: member.account && accountIdToPositionDict[member.account.id] || member.position.positionTitle
}
}))
}))}))
}))
};
Where the position would then be set based on the found accountId in the dictionary, or the original title if no match was found
const individualData = [{
"account": {
"id": "001b000003WnPy1AAF",
"fullName": "jeff bint"
},
"positions": [{
"id": "a16b0000004AxeBAAS",
"organizationId": "001b0000005gxmlAAA",
"organizationName": "a",
"positionTitle": "Senior Manager, Energy",
"positionLevel": "5-Middle Management & Advisers",
"isPrimary": true,
"startDate": "2016-10-07",
"endDate": null
}]
}, {
"account": {
"id": "0010X000048DDMsQAO",
"fullName": "edy long"
},
"positions": [{
"id": "a160X000004nKfhQAE",
"organizationId": "001b0000005gxmlAAA",
"organizationName": "a",
"positionTitle": "Managing Director",
"positionLevel": "4-Head of Business Unit/Head of Region",
"isPrimary": true,
"startDate": "2018-03-05",
"endDate": null
}]
}, {
"account": {
"id": "123",
"fullName": "john boer"
},
"positions": [{
"id": "325345634634",
"organizationId": "001b0000005gxmlAAA",
"organizationName": "a",
"positionTitle": "Managing Director",
"positionLevel": "4-Head of Business Unit/Head of Region",
"isPrimary": true,
"startDate": "2018-03-05",
"endDate": null
}]
}
];
const graphData = {
"name": "Annual meetings",
"engagementAreas": [{
"id": "1",
"engagementTypes": [{
"name": "forestry",
"engagements": []
},
{
"name": "houses",
"engagements": [{
"name": "engagement1",
"members": [{
"id": "e334", "account": {
"id": "eefe", "fullName": "jim bean"
},
"position": {
"id": "3434",
"positionTitle": "Manager"
}
}]
}]
},
{
"name": "landscaping",
"engagements": [{
"name": "engagement1343",
"members": [{
"id": "e334", "account": {
"id": "123", "fullName": "john boer"
},
"position": {
"id": "4545",
"positionTitle": "Senior Manager"
}
}]
}]
}
]
},
{
"name": "community days",
"engagementTypes": [{
"name": "skyscraping",
"engagements": []
},
{
"name": "tennis",
"engagements": [{
"name": "engagement346",
"members": [{
"id": "34", "account": {
"id": "0010X000048DDMsQAO", "fullName": "edy long"
},
"position": {
"id": "3999434",
"positionTitle": "Ultime Manager"
}
}]
}]
},
{
"name": "Juicing",
"engagements": [{
"name": "347343",
"members": [{
"id": "4546", "account": {
"id": "001b000003WnPy1AAF", "fullName": "jeff bint"
},
"position": {
"id": "35006",
"positionTitle": "Senior Ultimate Manager"
}
}]
}]
}]
}]
};
// first map the accountId to positions
const accountIdToPositionDict = individualData.reduce( (current, item) => {
current[item.account.id] = (item.positions.filter( position => position.isPrimary )[0] || {} ).positionTitle;
return current;
}, {} );
// then use it in the mapping function
const updatedGraphTable = { ...graphData,
engagementAreas: graphData.engagementAreas.map(area => ({ ...area,
engagementTypes: area.engagementTypes.map(type => ({ ...type,
engagements: type.engagements.map(engagement => ({ ...engagement,
members: engagement.members.map(member => ({ ...member,
position: { ...member.position,
// use the found positionTitle, or the original one that was given
positionTitle: member.account && accountIdToPositionDict[member.account.id] || member.position.positionTitle
}
}))
}))}))
}))
};
console.log( updatedGraphTable );
Try the code below.
accountPositions = {};
IndividualData.forEach((data) => {
accountPositions[data.account.id] = data.positions.filter((pos) => {return pos.isPrimary})[0].positionTitle;
});
graphData.engagementAreas.forEach((area) => {
area.engagementTypes.forEach((type) => {
type.engagements.forEach((engagement) => {
engagement.members.forEach((member) => {
if (!accountPositions[member.account.id]) return;
console.log('position updated from ', member.position.positionTitle, 'to', accountPositions[member.account.id]);
member.position.positionTitle = accountPositions[member.account.id];
});
});
});
});
I am using node and express and am sending value to front end in JSON
form like
[
{
"id": "1",
"name": "Plant Director",
"parentJobID": -1,
"children": [
{
"id": "19",
"name": "Operations Director",
"parentJobID": 1,
"children": [
{
"id": "16",
"name": "Financial planning and costs Manager",
"parentJobID": 19,
"children": [
{
"id": "14",
"name": "Cost Analyst",
"parentJobID": 16,
"children": []
},
{
"id": "15",
"name": "Head of Costs",
"parentJobID": 16,
"children": []
}
]
},
{
"id": "17",
"name": "Manufacturing Manager",
"parentJobID": 19,
"children": [
{
"id": "2",
"name": "Head of Security",
"parentJobID": 17,
"children": [
{
"id": "3",
"name": "Asistente Ejecutiva",
"parentJobID": 2,
"children": []
},
{
"id": "8",
"name": "Jefe de Mantenimiento",
"parentJobID": 2,
"children": []
},
{
"id": "27",
"name": "Jefe Aseguramiento de Calidad",
"parentJobID": 2,
"children": [
{
"id": "28",
"name": "Jefe Seguridad Alimentaria",
"parentJobID": 27,
"children": [
{
"id": "33",
"name": "Operario Fabricación A (2)",
"parentJobID": 28,
"children": []
},
{
"id": "34",
"name": "Operario Fabricación B (2)",
"parentJobID": 28,
"children": []
}
]
},
{
"id": "29",
"name": "Especialista Aseguramiento de Calidad",
"parentJobID": 27,
"children": []
},
{
"id": "30",
"name": "Especialista en Microbiología",
"parentJobID": 27,
"children": []
},
{
"id": "31",
"name": "Especialista en Evaluación Sensorial",
"parentJobID": 27,
"children": []
},
{
"id": "32",
"name": "Técnico Aseguramiento de Calidad",
"parentJobID": 27,
"children": []
}
]
}
]
},
{
"id": "4",
"name": "Production Manager",
"parentJobID": 17,
"children": []
},
{
"id": "5",
"name": "Head of Maintenance",
"parentJobID": 17,
"children": []
},
{
"id": "6",
"name": "Quality Control Manager",
"parentJobID": 17,
"children": [
{
"id": "7",
"name": "Técnico Medio Ambiente",
"parentJobID": 6,
"children": []
},
{
"id": "23",
"name": "Quality Control Technician 1",
"parentJobID": 6,
"children": [
{
"id": "25",
"name": "Operario Fabricación B",
"parentJobID": 23,
"children": []
},
{
"id": "26",
"name": "Operario Fabricación D",
"parentJobID": 23,
"children": []
}
]
},
{
"id": "24",
"name": "Quality Control Technician 2",
"parentJobID": 6,
"children": []
}
]
},
{
"id": "9",
"name": "Warehouse Manager",
"parentJobID": 17,
"children": []
},
{
"id": "10",
"name": "Head of Planning",
"parentJobID": 17,
"children": [
{
"id": "20",
"name": "Operario Mtto A (2)",
"parentJobID": 10,
"children": []
}
]
},
{
"id": "11",
"name": "Head of Continuous Improvement",
"parentJobID": 17,
"children": [
{
"id": "21",
"name": "Operario Servicios A (2)",
"parentJobID": 11,
"children": []
}
]
},
{
"id": "12",
"name": "Head of Supplies",
"parentJobID": 17,
"children": []
},
{
"id": "13",
"name": "Process Manager",
"parentJobID": 17,
"children": []
},
{
"id": "18",
"name": "IT Manager",
"parentJobID": 17,
"children": []
}
]
}
]
},
{
"id": "35",
"name": "[ LINEA DE PRODUCCION ]",
"parentJobID": 1,
"children": []
}
]
},
{
"id": "22",
"name": "Extrusion Area",
"parentJobID": -1,
"children": []
}
]
In front end am calling a function to create the hierarchy
<script>
function sim(list)
{
for (var i = 0; i < list.length; i++) {
var li = document.createElement('li');
li.innerHTML = list[i].name;
if (list[i].children.length > 0) {
var ul = document.createElement('ul');
li.appendChild(ul);
print_list(list[i].children, ul);
}
$("#jqxTree").appendChild(li);
}
}
sim("<%= list %>");
</script>
<ul id='jqxTree'>
</ul>
Its giving me error in this line if (list[i].children.length > 0) { as
Cannot read property 'length' of undefined
You have to parse the JSON first. look into the following code if you send the json as String.
json = JSON.parse(list);
$.each(json, function(idx, obj) {
alert(obj.name + " - " + obj.children.length);
});
My current json (which I created for generating tree structure) is as follows:
[{"text":"glossary","id":"599","parentid":"-1"},
{"text":"title","id":"600","parentid":"599"},
{"text":"","id":"601","parentid":"600"},
{"text":"GlossDiv","id":"602","parentid":"599"},
{"text":"GlossList","id":"603","parentid":"602"},
{"text":"GlossEntry","id":"604","parentid":"603"},
{"text":"GlossTerm","id":"605","parentid":"604"},
{"text":"Standard Generalized Markup Language","id":"606","parentid":"605"},
{"text":"GlossSee","id":"607","parentid":"604"},
{"text":"markup","id":"608","parentid":"607"},
{"text":"SortAs","id":"609","parentid":"604"},
{"text":"SGML","id":"610","parentid":"609"},
{"text":"GlossDef","id":"611","parentid":"604"},
{"text":"para","id":"612","parentid":"611"},
{"text":"","id":"613","parentid":"612"},
{"text":"GlossSeeAlso","id":"614","parentid":"611"},
{"text":"","id":"615","parentid":"614"},
{"text":"XML","id":"616","parentid":"614"},
{"text":"ID","id":"617","parentid":"604"},
{"text":"SGML","id":"618","parentid":"617"},
{"text":"Acronym","id":"619","parentid":"604"},
{"text":"SGML","id":"620","parentid":"619"},
{"text":"Abbrev","id":"621","parentid":"604"},
{"text":"ISO 8879:1986","id":"622","parentid":"621"},
{"text":"title","id":"623","parentid":"602"},
{"text":"","id":"624","parentid":"623"}]`
How to generate a nested json for the above array in Javascript?
You can create a lookup dictionary, to hold the parents, and reference those as you iterate all the entries.
var dictionary = {};
for (var i = 0; i < data.length; i++) {
dictionary[data[i].id] = data[i];
}
for (var i = 0; i < data.length; i++) {
if (data[i].parentid) {
var parent = dictionary[data[i].parentid];
if (parent) {
if (!parent.children) {
parent.children = [];
}
parent.children.push(data[i]);
}
}
}
JSFiddle: http://jsfiddle.net/TrueBlueAussie/y22ctL8o/1/
Which results in a structure like this:
[{
"text": "glossary",
"id": "599",
"parentid": "-1",
"children": [{
"text": "title",
"id": "600",
"parentid": "599",
"children": [{
"text": "",
"id": "601",
"parentid": "600"
}]
}, {
"text": "GlossDiv",
"id": "602",
"parentid": "599",
"children": [{
"text": "GlossList",
"id": "603",
"parentid": "602",
"children": [{
"text": "GlossEntry",
"id": "604",
"parentid": "603",
"children": [{
"text": "GlossTerm",
"id": "605",
"parentid": "604",
"children": [{
"text": "Standard Generalized Markup Language",
"id": "606",
"parentid": "605"
}]
}, {
"text": "GlossSee",
"id": "607",
"parentid": "604",
"children": [{
"text": "markup",
"id": "608",
"parentid": "607"
}]
}, {
"text": "SortAs",
"id": "609",
"parentid": "604",
"children": [{
"text": "SGML",
"id": "610",
"parentid": "609"
}]
}, {
"text": "GlossDef",
"id": "611",
"parentid": "604",
"children": [{
"text": "para",
"id": "612",
"parentid": "611",
"children": [{
"text": "",
"id": "613",
"parentid": "612"
}]
}, {
"text": "GlossSeeAlso",
"id": "614",
"parentid": "611",
"children": [{
"text": "",
"id": "615",
"parentid": "614"
}, {
"text": "XML",
"id": "616",
"parentid": "614"
}]
}]
}, {
"text": "ID",
"id": "617",
"parentid": "604",
"children": [{
"text": "SGML",
"id": "618",
"parentid": "617"
}]
}, {
"text": "Acronym",
"id": "619",
"parentid": "604",
"children": [{
"text": "SGML",
"id": "620",
"parentid": "619"
}]
}, {
"text": "Abbrev",
"id": "621",
"parentid": "604",
"children": [{
"text": "ISO 8879:1986",
"id": "622",
"parentid": "621"
}]
}]
}]
}, {
"text": "title",
"id": "623",
"parentid": "602",
"children": [{
"text": "",
"id": "624",
"parentid": "623"
}]
}]
}]
}, {
"text": "title",
"id": "600",
"parentid": "599",
"children": [{
"text": "",
"id": "601",
"parentid...rkup",
"id": "608",
"parentid": "607"
}]
}, {
"text": "markup",
"id": "608",
"parentid": "607"
}, {
"text": "SortAs",
"id": "609",
"parentid": "604",
"children": [{
"text": "SGML",
"id": "610",
"parentid": "609"
}]
}, {
"text": "SGML",
"id": "610",
"parentid": "609"
}, {
"text": "GlossDef",
"id": "611",
"parentid": "604",
"children": [{
"text": "para",
"id": "612",
"parentid": "611",
"children": [{
"text": "",
"id": "613",
"parentid": "612"
}]
}, {
"text": "GlossSeeAlso",
"id": "614",
"parentid": "611",
"children": [{
"text": "",
"id": "615",
"parentid": "614"
}, {
"text": "XML",
"id": "616",
"parentid": "614"
}]
}]
}, {
"text": "para",
"id": "612",
"parentid": "611",
"children": [{
"text": "",
"id": "613",
"parentid": "612"
}]
}, {
"text": "",
"id": "613",
"parentid": "612"
}, {
"text": "GlossSeeAlso",
"id": "614",
"parentid": "611",
"children": [{
"text": "",
"id": "615",
"parentid": "614"
}, {
"text": "XML",
"id": "616",
"parentid": "614"
}]
}, {
"text": "",
"id": "615",
"parentid": "614"
}, {
"text": "XML",
"id": "616",
"parentid": "614"
}, {
"text": "ID",
"id": "617",
"parentid": "604",
"children": [{
"text": "SGML",
"id": "618",
"parentid": "617"
}]
}, {
"text": "SGML",
"id": "618",
"parentid": "617"
}, {
"text": "Acronym",
"id": "619",
"parentid": "604",
"children": [{
"text": "SGML",
"id": "620",
"parentid": "619"
}]
}, {
"text": "SGML",
"id": "620",
"parentid": "619"
}, {
"text": "Abbrev",
"id": "621",
"parentid": "604",
"children": [{
"text": "ISO 8879:1986",
"id": "622",
"parentid": "621"
}]
}, {
"text": "ISO 8879:1986",
"id": "622",
"parentid": "621"
}, {
"text": "title",
"id": "623",
"parentid": "602",
"children": [{
"text": "",
"id": "624",
"parentid": "623"
}]
}, {
"text": "",
"id": "624",
"parentid": "623"
}]
But this all depends on what you intend to do with the result. The question is currently ambiguous.
Note: The above double-iteration of data allows for the parents to appear after the children (which may or may not be the case). If the parents always appear first you can combine the logic into one loop.
e.g.
var dictionary = {};
for (var i = 0; i < data.length; i++) {
dictionary[data[i].id] = data[i];
if (data[i].parentid) {
var parent = dictionary[data[i].parentid];
if (parent) {
if (!parent.children) {
parent.children = [];
}
parent.children.push(data[i]);
}
}
}