Json data to javaScript Treeview - javascript

hello there is a json data as below.
var arr = [{
"ID": 1,
"parentID": 0,
"Phone": "(403) 125-2552",
"City": "Coevorden",
"Name": "Grady"
}, {
"ID": 2,
"parentID": 0,
"Phone": "(979) 486-1932",
"City": "Chełm",
"Name": "Scarlet"
}, {
"ID": 3,
"parentID": 0,
"Phone": "(573) 685-8350",
"City": "Wardha",
"Name": "Adria"
}, {
"ID": 4,
"parentID": 3,
"Phone": "(630) 292-9737",
"City": "Villers-la-Loue",
"Name": "Xerxes"
}, {
"ID": 5,
"parentID": 0,
"Phone": "(755) 968-6539",
"City": "Gönen",
"Name": "Madeson"
}, {
"ID": 6,
"parentID": 5,
"Phone": "(644) 892-5485",
"City": "Timkur",
"Name": "Rae"
}, {
"ID": 7,
"parentID": 0,
"Phone": "(896) 297-6568",
"City": "Louvain-la-Neuve",
"Name": "Celeste"
}, {
"ID": 8,
"parentID": 5,
"Phone": "(168) 452-3538",
"City": "Worksop",
"Name": "Rowan"
}, {
"ID": 9,
"parentID": 5,
"Phone": "(873) 337-9560",
"City": "Bad Neuenahr-Ahrweiler",
"Name": "Kendall"
}, {
"ID": 10,
"parentID": 0,
"Phone": "(450) 579-0491",
"City": "MIDdelburg",
"Name": "Madaline"
}, {
"ID": 11,
"parentID": 0,
"Phone": "(111) 162-2502",
"City": "Birecik",
"Name": "Chandler"
}, {
"ID": 12,
"parentID": 8,
"Phone": "(712) 483-3905",
"City": "Courbevoie",
"Name": "Craig"
}, {
"ID": 13,
"parentID": 8,
"Phone": "(872) 499-5833",
"City": "Cuccaro Vetere",
"Name": "Basia"
}, {
"ID": 14,
"parentID": 6,
"Phone": "(724) 797-0077",
"City": "Portree",
"Name": "Elmo"
}, {
"ID": 15,
"parentID": 5,
"Phone": "(366) 967-0433",
"City": "Dublin",
"Name": "Cairo"
}, {
"ID": 16,
"parentID": 11,
"Phone": "(147) 708-7321",
"City": "Rivière-du-Loup",
"Name": "Mannix"
}, {
"ID": 17,
"parentID": 0,
"Phone": "(407) 519-9894",
"City": "Roubaix",
"Name": "Justine"
}]
.
.
.
I wanted to make a treeview of this data and I got a result like the one below. No problem, it works properly.
[
{
"ID": 1,
"parentID": 0,
"Phone": "(403) 125-2552",
"City": "Coevorden",
"Name": "Grady"
},
{
"ID": 2,
"parentID": 0,
"Phone": "(979) 486-1932",
"City": "Chełm",
"Name": "Scarlet",
"children": [
{
"ID": 30,
"parentID": 2,
"Phone": "(641) 756-7073",
"City": "Harrison Hot Springs",
"Name": "Hamilton",
"children": [
{
"ID": 54,
"parentID": 30,
"Phone": "(800) 876-5942",
"City": "Ribnitz-Damgarten",
"Name": "Kelsie",
"children": [
{
"ID": 62,
"parentID": 54,
"Phone": "(523) 159-2911",
"City": "Biała Podlaska",
"Name": "Clio"
}
]
},
{
"ID": 87,
"parentID": 30,
"Phone": "(500) 895-9220",
"City": "Piracicaba",
"Name": "Maya"
}
]
},
{
"ID": 40,
"parentID": 2,
"Phone": "(921) 336-7339",
"City": "Namur",
"Name": "Lionel"
},
{
"ID": 43,
"parentID": 2,
"Phone": "(410) 695-8540",
"City": "Saint-Laurent",
"Name": "Deanna",
"children": [
{
"ID": 63,
"parentID": 43,
"Phone": "(475) 190-5102",
"City": "Nicoya",
"Name": "Nola"
},
{
"ID": 98,
"parentID": 43,
"Phone": "(268) 572-5059",
"City": "San Marcello Pistoiese",
"Name": "Marny"
}
]
}
]
},
{
"ID": 3,
"parentID": 0,
"Phone": "(573) 685-8350",
"City": "Wardha",
"Name": "Adria",
"children": [
{
"ID": 4,
"parentID": 3,
"Phone": "(630) 292-9737",
"City": "Villers-la-Loue",
"Name": "Xerxes",
"children": [
{
"ID": 44,
"parentID": 4,
"Phone": "(287) 866-8953",
"City": "Fiuminata",
"Name": "Darius",
"children": [
{
"ID": 47,
"parentID": 44,
"Phone": "(779) 411-0381",
"City": "Pontedera",
"Name": "Harding",
"children": [
{
"ID": 92,
"parentID": 47,
"Phone": "(925) 263-0254",
"City": "Curacaví",
"Name": "Aristotle"
}
]
}
]
},
{
"ID": 56,
"parentID": 4,
"Phone": "(963) 719-2718",
"City": "Gore",
"Name": "Rafael"
}
]
},
{
"ID": 58,
"parentID": 3,
"Phone": "(464) 318-7548",
"City": "Curepto",
"Name": "Leila"
}
]
.
.
.
My main question is parentID: I don't want to write parentID to objects that write 0. But when I remove the places that say parentID: 0, it doesn't work properly. Can you help?
The code I run is:
tree = function(array) {
var o = {
ID: 0
}
function arrGet(o) {
if (Array.isArray(o.children)) {
o.children.forEach(arrGet);
}
}
array.forEach(function(a) {
o[a.ID] = o[a.ID] || {
ID: a.ID,
parentID: a.parentID,
Phone: a.Phone,
City: a.City,
Name: a.Name
};
a.children = o[a.ID].children;
o[a.parentID] = o[a.parentID] || {
ID: a.parentID
};
o[a.parentID].children = o[a.parentID].children || [];
o[a.parentID].children.push(o[a.ID]);
});
arrGet(o[0]);
return o[0].children;
}(arr);
document.writeln('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');

just find the way inside the tree, based on origin array...
Full code:
/*--------------------------------------------------------*\
| treeMaker : JSON [Array of obj] to Treeview (function) |
| |
| input array objets must be like { ID,[ parentID ] ...} |
\* -------------------------------------------------------*/
const treeMaker = arr =>
arr.reduce((tree,{parentID,...useful},_,Origin)=>
{
if (!parentID) tree.push({...useful}) // direct case!
else
{
let path = { children: tree } // path for insert
, road = [ Origin.find(x=>x.ID===parentID) ] // every road has an end
;
while(!!road[0].parentID) // as long as a parentID property exist
{
road.unshift(Origin.find(x=>x.ID===road[0].parentID)) // get road origin
}
for(let way of road) // make your way by following the road
{
path = path.children.find(x=>x.ID===way.ID) // change the path to children
}
if (!path.children) path.children = [] // if not exist, add children array
;
path.children.push({...useful}) // copy all useful items
}
return tree // back to the trees!
},[])
/*--------------------------------------------------------*/
// test part
const myArr =
[ { ID: 1, Phone: '(403) 125-2552', City: 'Coevorden', Name: 'Grady' }
, { ID: 2, Phone: '(979) 486-1932', City: 'Chełm', Name: 'Scarlet' }
, { ID: 3, Phone: '(573) 685-8350', City: 'Wardha', Name: 'Adria' }
, { ID: 4, parentID: 3, Phone: '(630) 292-9737', City: 'Villers-la-Loue', Name: 'Xerxes' }
, { ID: 5, Phone: '(755) 968-6539', City: 'Gönen', Name: 'Madeson' }
, { ID: 6, parentID: 5, Phone: '(644) 892-5485', City: 'Timkur', Name: 'Rae' }
, { ID: 7, Phone: '(896) 297-6568', City: 'Louvain-la-Neuve', Name: 'Celeste' }
, { ID: 8, parentID: 5, Phone: '(168) 452-3538', City: 'Worksop', Name: 'Rowan' }
, { ID: 9, parentID: 5, Phone: '(873) 337-9560', City: 'Bad Neuenahr-Ahrweiler', Name: 'Kendall' }
, { ID: 10, Phone: '(450) 579-0491', City: 'MIDdelburg', Name: 'Madaline' }
, { ID: 11, Phone: '(111) 162-2502', City: 'Birecik', Name: 'Chandler' }
, { ID: 12, parentID: 8, Phone: '(712) 483-3905', City: 'Courbevoie', Name: 'Craig' }
, { ID: 13, parentID: 8, Phone: '(872) 499-5833', City: 'Cuccaro Vetere', Name: 'Basia' }
, { ID: 14, parentID: 6, Phone: '(724) 797-0077', City: 'Portree', Name: 'Elmo' }
, { ID: 15, parentID: 5, Phone: '(366) 967-0433', City: 'Dublin', Name: 'Cairo' }
, { ID: 16, parentID: 11, Phone: '(147) 708-7321', City: 'Rivière-du-Loup', Name: 'Mannix' }
, { ID: 17, Phone: '(407) 519-9894', City: 'Roubaix', Name: 'Justine' }
, { ID: 18, parentID: 14, Phone: '(938) 793-5446', City: 'Eugene', Name: 'Dahlia' }
, { ID: 19, parentID: 5, Phone: '(425) 682-2189', City: 'Salisbury', Name: 'Irene' }
, { ID: 20, parentID: 12, Phone: '(351) 187-8200', City: 'Garaguso', Name: 'Trevor' }
, { ID: 21, Phone: '(601) 944-5214', City: 'Pointe-au-Pic', Name: 'Iris' }
, { ID: 22, parentID: 20, Phone: '(479) 532-6127', City: 'Salt Lake City', Name: 'Fleur' }
, { ID: 23, parentID: 19, Phone: '(339) 973-1695', City: 'Meldert', Name: 'Hayley' }
, { ID: 24, parentID: 11, Phone: '(946) 766-1649', City: 'Corral', Name: 'Baker' }
, { ID: 25, Phone: '(964) 413-7033', City: 'Joliet', Name: 'Leo' }
, { ID: 26, parentID: 7, Phone: '(898) 476-0059', City: 'Burntisland', Name: 'Rigel' }
]
const myTree = treeMaker ( myArr )
document.write('<pre>myTree:\n')
document.write(JSON.stringify(myTree,0,2))
document.write('</pre>')
In this algorithm, the destructuring assignment is used on each element of the original table, as follows:
let element1 = { ID:6, parentID:5, City:'Timkur', Name:'Rae' }
let {parentID, ...useful} = element1 // destructuring assignment
console.log( parentID ) // return 5
console.log( useful ) // return object { ID:6, City:'Timkur', Name:'Rae' }
console.log ( !parentID ) // return false
without parentID property:
let element2 = { ID:7, City:'Louvain-la-Neuve', Name: 'Celeste' }
let {parentID, ...useful} = element2 // destructuring assignment
console.log( parentID ) // undefined
console.log( useful ) // return object { ID:7, ....
console.log ( !parentID ) // return true
In this code the destructuring assignment is directly used inside the argument list of the array method reduce (see further)
About the use of the Array.reduce method (see mdn for more details):
const arr_tree = arr.reduce(function(tree,curr,idx,Origin) {…}, initilial_tree);
same as arrow notation:
a) const arr_tree = arr.reduce((tree,curr,_,Origin)=>{…}, []);
b) const arr_tree = arr.reduce((tree,{parentID,...useful},_,Origin)=>
Arrguments:
tree, array under construction (initialized by initilial_tree, here=[] =>empty array), this element must be returned at each iteration
curr: the current element (as in a loop on the array), **used in an destructuring assignment
{parentID,...useful} = curr ( please compare a) and b) )
idx: the index of the element (curr) on the array (not useful here and replaced by _)
Origin: the original table used by the method
the algorithm:
for any element with a parentID, its parent must be found in the tree under construction.
That is, for an X element with a parentID there is an X-1 element with that ID.
And if this X-1 element has itself a ParentID, there is also another X-2 element with this ID.
And so on, until we find an X-n element that has no ParentID.
This X-N element is directly at the root of the result array.
All that remains is to follow the reverse path in the tree structure under construction:
we look for the position Xn at the level of its root, then on this one the element X- (n-1) among its children, until finding that of the element X-1 where we can add the element X in the list of its children.
Making sure to add an empty list of children, if X-1 had no children yet.
There are therefore 2 parts:
1- go up the road from X-1 to the X-n elements using the origin table
let road = [ Origin.find(x=>x.ID===parentID) ] // every road has an end
while(!!road[0].parentID) // as long as a parentID property exist
{
road.unshift(Origin.find(x=>x.ID===road[0].parentID)) // get road origin
}
if we start from element X = { ID: 12, parentID: 8, ... Name: 'Craig'} (where the parentID value is 8)
the result is :
road = [ { ID: 5, ... Name: 'Madeson' }
, { ID: 8, parentID: 5,... Name: 'Rowan' }
]
note 1:
the use of the array.unshift() method to add the elements from the top
/ unlike the array.push() method, the last element entered is therefore in position zero,
which allows the test to be passed
(!!road[0].parentID)
with always an index value at zero.
...For the double exclamation mark look here
note 2:
the road array only contains "pointers" to the objects of the original array.
2- find the path of element X-1 in tree structure under construction
let path = { children: tree } // path for insert
for(let way of road) // make your way by following the road
{
path = path.children.find(x=>x.ID===way.ID) // change the path to children
}
note X: I use my sort of Whitesmiths style code formatting for years
for info, it's look like that:
├─1_Grady
├─2_Scarlet
├─3_Adria─┐
│ └─4_Xerxes
├─5_Madeson─┐
│ ├─6_Rae─┐
│ │ └─14_Elmo─┐
│ │ └─18_Dahlia
│ ├─8_Rowan─┐
│ │ ├─12_Craig─┐
│ │ │ └─20_Trevor─┐
│ │ │ └─22_Fleur
│ │ └─13_Basia
│ ├─9_Kendall
│ ├─15_Cairo
│ └─19_Irene─┐
│ └─23_Hayley
├─7_Celeste─┐
│ └─26_Rigel
├─10_Madaline
├─11_Chandler─┐
│ ├─16_Mannix
│ └─24_Baker
├─17_Justine
├─21_Iris
└─25_Leo

What you can do is to use the delete operator when parentID is equal to 0. This will delete the property from the object, hence not displaying it.
var arr = [{
"ID": 1,
"parentID": 0,
"Phone": "(403) 125-2552",
"City": "Coevorden",
"Name": "Grady"
}, {
"ID": 2,
"parentID": 0,
"Phone": "(979) 486-1932",
"City": "Chełm",
"Name": "Scarlet"
}, {
"ID": 3,
"parentID": 0,
"Phone": "(573) 685-8350",
"City": "Wardha",
"Name": "Adria"
}, {
"ID": 4,
"parentID": 3,
"Phone": "(630) 292-9737",
"City": "Villers-la-Loue",
"Name": "Xerxes"
}, {
"ID": 5,
"parentID": 0,
"Phone": "(755) 968-6539",
"City": "Gönen",
"Name": "Madeson"
}, {
"ID": 6,
"parentID": 5,
"Phone": "(644) 892-5485",
"City": "Timkur",
"Name": "Rae"
}, {
"ID": 7,
"parentID": 0,
"Phone": "(896) 297-6568",
"City": "Louvain-la-Neuve",
"Name": "Celeste"
}, {
"ID": 8,
"parentID": 5,
"Phone": "(168) 452-3538",
"City": "Worksop",
"Name": "Rowan"
}, {
"ID": 9,
"parentID": 5,
"Phone": "(873) 337-9560",
"City": "Bad Neuenahr-Ahrweiler",
"Name": "Kendall"
}, {
"ID": 10,
"parentID": 0,
"Phone": "(450) 579-0491",
"City": "MIDdelburg",
"Name": "Madaline"
}, {
"ID": 11,
"parentID": 0,
"Phone": "(111) 162-2502",
"City": "Birecik",
"Name": "Chandler"
}, {
"ID": 12,
"parentID": 8,
"Phone": "(712) 483-3905",
"City": "Courbevoie",
"Name": "Craig"
}, {
"ID": 13,
"parentID": 8,
"Phone": "(872) 499-5833",
"City": "Cuccaro Vetere",
"Name": "Basia"
}, {
"ID": 14,
"parentID": 6,
"Phone": "(724) 797-0077",
"City": "Portree",
"Name": "Elmo"
}, {
"ID": 15,
"parentID": 5,
"Phone": "(366) 967-0433",
"City": "Dublin",
"Name": "Cairo"
}, {
"ID": 16,
"parentID": 11,
"Phone": "(147) 708-7321",
"City": "Rivière-du-Loup",
"Name": "Mannix"
}, {
"ID": 17,
"parentID": 0,
"Phone": "(407) 519-9894",
"City": "Roubaix",
"Name": "Justine"
}];
tree = function(array) {
var o = {
ID: 0
}
function arrGet(o) {
if (Array.isArray(o.children)) {
o.children.forEach(arrGet);
}
}
array.forEach(function(a) {
o[a.ID] = o[a.ID] || {
ID: a.ID,
parentID: a.parentID,
Phone: a.Phone,
City: a.City,
Name: a.Name
};
if(a.parentID === 0)
delete o[a.ID].parentID;
a.children = o[a.ID].children;
o[a.parentID] = o[a.parentID] || {
ID: a.parentID
};
o[a.parentID].children = o[a.parentID].children || [];
o[a.parentID].children.push(o[a.ID]);
});
arrGet(o[0]);
return o[0].children;
}(arr);
document.writeln('<pre>' + JSON.stringify(tree, 0, 4) + '</pre>');

var arr = [{
"ID": 1,
"Phone": "(403) 125-2552",
"City": "Coevorden",
"Name": "Grady"
}, {
"ID": 2,
"Phone": "(979) 486-1932",
"City": "Chełm",
"Name": "Scarlet"
}, {
"ID": 3,
"Phone": "(573) 685-8350",
"City": "Wardha",
"Name": "Adria"
}, {
"ID": 4,
"parentID": 3,
"Phone": "(630) 292-9737",
"City": "Villers-la-Loue",
"Name": "Xerxes"
}, {
"ID": 5,
"Phone": "(755) 968-6539",
"City": "Gönen",
"Name": "Madeson"
}, {
"ID": 6,
"parentID": 5,
"Phone": "(644) 892-5485",
"City": "Timkur",
"Name": "Rae"
}, {
"ID": 7,
"Phone": "(896) 297-6568",
"City": "Louvain-la-Neuve",
"Name": "Celeste"
}, {
"ID": 8,
"parentID": 5,
"Phone": "(168) 452-3538",
"City": "Worksop",
"Name": "Rowan"
}, {
"ID": 9,
"parentID": 5,
"Phone": "(873) 337-9560",
"City": "Bad Neuenahr-Ahrweiler",
"Name": "Kendall"
}, {
"ID": 10,
"Phone": "(450) 579-0491",
"City": "MIDdelburg",
"Name": "Madaline"
}, {
"ID": 11,
"Phone": "(111) 162-2502",
"City": "Birecik",
"Name": "Chandler"
}, {
"ID": 12,
"parentID": 8,
"Phone": "(712) 483-3905",
"City": "Courbevoie",
"Name": "Craig"
}, {
"ID": 13,
"parentID": 8,
"Phone": "(872) 499-5833",
"City": "Cuccaro Vetere",
"Name": "Basia"
}, {
"ID": 14,
"parentID": 6,
"Phone": "(724) 797-0077",
"City": "Portree",
"Name": "Elmo"
}, {
"ID": 15,
"parentID": 5,
"Phone": "(366) 967-0433",
"City": "Dublin",
"Name": "Cairo"
}, {
"ID": 16,
"parentID": 11,
"Phone": "(147) 708-7321",
"City": "Rivière-du-Loup",
"Name": "Mannix"
}, {
"ID": 17,
"Phone": "(407) 519-9894",
"City": "Roubaix",
"Name": "Justine"
}, {
"ID": 18,
"parentID": 14,
"Phone": "(938) 793-5446",
"City": "Eugene",
"Name": "Dahlia"
}, {
"ID": 19,
"parentID": 5,
"Phone": "(425) 682-2189",
"City": "Salisbury",
"Name": "Irene"
}, {
"ID": 20,
"parentID": 12,
"Phone": "(351) 187-8200",
"City": "Garaguso",
"Name": "Trevor"
}, {
"ID": 21,
"Phone": "(601) 944-5214",
"City": "Pointe-au-Pic",
"Name": "Iris"
}, {
"ID": 22,
"parentID": 20,
"Phone": "(479) 532-6127",
"City": "Salt Lake City",
"Name": "Fleur"
}, {
"ID": 23,
"parentID": 19,
"Phone": "(339) 973-1695",
"City": "Meldert",
"Name": "Hayley"
}, {
"ID": 24,
"parentID": 11,
"Phone": "(946) 766-1649",
"City": "Corral",
"Name": "Baker"
}, {
"ID": 25,
"Phone": "(964) 413-7033",
"City": "Joliet",
"Name": "Leo"
}, {
"ID": 26,
"parentID": 7,
"Phone": "(898) 476-0059",
"City": "Burntisland",
"Name": "Rigel"
}]
original data like this

Related

How to change the format of an array of objects based on ParentID

I am trying to change the format of an array of objects based on a field called ParentID.
Here is a sample of data:
var JsonVal = "data": {
"Factorid": 197325,
"orders": [
{
"pID": 794522,
"Count": 1,
"ParentID": 794551,
"Description": "",
"productid": "1428539",
"UnitPrice": "300000",
},
{
"pID": 794525,
"Count": 1,
"ParentID": 794551,
"Description": "",
"productid": "1428543",
"UnitPrice": "600000",
},
{
"pID": 794550,
"Count": 2,
"ParentID": 0,
"Description": "",
"productid": "1428648",
"UnitPrice": "60000",
},
{
"pID": 794551,
"Count": 1,
"ParentID": 0,
"Description": "",
"productid": "1428647",
"UnitPrice": "250000",
} ,
{
"pID": 794526,
"Count": 3,
"ParentID": 794550,
"Description": "",
"productid": "1428548",
"UnitPrice": "600000",
},
{
"pID": 794527,
"Count": 1,
"ParentID": 0,
"Description": "",
"productid": "1428542",
"UnitPrice": "400000",
},
]
}
As you can see every object has a ParentID. I want to say that if ParentID is 0, it will be known as a parent and add a field call children which its value is null. However if ParentID is not 0 , it will mean that this Object is a child of another Object that its pID is the same as ParentID child Object.The final JSON should be like this :
"data": {
"Factorid": 197325,
"orders": [
{
"pID": 794550,
"Count": 2,
"ParentID": 0,
"Description": "",
"productid": "1428648",
"UnitPrice": "60000",
"children": "[{
'pID': 794526,
'Count':3,
'ParentID': 794550,
'Description': '',
'productid': '1428548',
'UnitPrice': '600000',
}]",
},
{
"pID": 794551,
"Count": 1,
"ParentID": 0,
"Description": "",
"productid": "1428647",
"UnitPrice": "250000",
"children":"[
{
'pID': 794522,
'Count': 1,
'ParentID': 794551,
'Description': '',
'productid': '1428539',
'UnitPrice': '300000',
},
{
'pID': 794525,
'Count': 1,
'ParentID': 794551,
'Description': '',
'productid': '1428543',
'UnitPrice': '600000',
},
]",
} ,
{
"pID": 794527,
"Count": 1,
"ParentID": 0,
"Description": "",
"productid": "1428542",
"UnitPrice": "400000",
"children":"",
},
]
}
children should be added to any object which is parent and also children is always a string field.
I wrote a code but I do not know how to handle it?
JsonVal.orders.forEach(orders => {
if(orders.ParentID == 0){
orders.children="";
}else{
if(orders.ParentID == new_rows){
JsonVal.orders = JsonVal.orders.filter(item => item.ParentID == orders.ParentID);
}
}
});
You basically filter your list of orders if it is a "rootOrder" which means that it has one or multiple children.
Next, you filter your list again by matching the ParentId to the root.pID
// input
const JsonVal = {
data: {
Factorid: 197325,
orders: [
{
pID: 794522,
Count: 1,
ParentID: 794551,
Description: "",
productid: "1428539",
UnitPrice: "300000",
},
{
pID: 794525,
Count: 1,
ParentID: 794551,
Description: "",
productid: "1428543",
UnitPrice: "600000",
},
{
pID: 794550,
Count: 2,
ParentID: 0,
Description: "",
productid: "1428648",
UnitPrice: "60000",
},
{
pID: 794551,
Count: 1,
ParentID: 0,
Description: "",
productid: "1428647",
UnitPrice: "250000",
},
{
pID: 794526,
Count: 3,
ParentID: 794550,
Description: "",
productid: "1428548",
UnitPrice: "600000",
},
{
pID: 794527,
Count: 1,
ParentID: 0,
Description: "",
productid: "1428542",
UnitPrice: "400000",
},
],
},
};
function mapOrders(orders) {
const rootOrders = orders.filter((order) => order.ParentID === 0);
return rootOrders.map((rootOrder) => {
const children = orders.filter((order) => order.ParentID === rootOrder.pID);
return {
...rootOrder,
children: children.length ? children : "",
};
});
}
// output
const mappedJsonVal = {
...JsonVal,
data: {
...JsonVal.data,
orders: mapOrders(JsonVal.data.orders),
},
};

format object array to grouped nested array object to generate antd tree table

I get the following array object from response and I need to implement antd tree table in my react application using this array object.
const students=[
{
"index": "5260574",
"studentName": "David Sinclair",
"marks": "177",
"gender": "M",
"resultId": 16,
"province": {
"code": "1",
"name": "Andregan"
},
"county": {
"name": "Silk",
"code": "21"
},
"city": {
"code": "234",
"name": "Meegan"
},
"rural": {
"code": "41",
"name": "Thumphil"
},
"canEvaluate": true
},
{
"index": "5259991",
"studentName": "KALURA GEETH DAMS",
"marks": "177",
"gender": "M",
"resultId": 17,
"province": {
"code": "1",
"name": "Andregan"
},
"county": {
"name": "Silk",
"code": "21"
},
"city": {
"code": "234",
"name": "Meegan"
},
"rural": {
"code": "41",
"name": "Thumphil"
},
"canEvaluate": true
},
{
"index": "5260534",
"studentName": "Mathew Jenkins",
"marks": "157",
"gender": "M",
"resultId": 21,
"province": {
"code": "1",
"name": "Andregan"
},
"county": {
"name": "Silk",
"code": "21"
},
"city": {
"code": "44",
"name": "Wrens"
},
"rural": {
"code": "49",
"name": "Cardin"
},
"canEvaluate": true
},
{
"index": "5260680",
"studentName": "MEDIW KENULA",
"marks": "177",
"gender": "M",
"resultId": 18,
"province": {
"code": "2",
"name": "Kiren"
},
"county": {
"name": "Georgia",
"code": "23"
},
"city": {
"code": "34",
"name": "Eden Hill"
},
"rural": {
"code": "99",
"name": "Southern Sea"
},
"canEvaluate": true
}
]
I want to group this response as province , county, city, rural wise as shown in below rendered antd tree table.
.
To get above tree table and get selected students, I need to format the response as below for the dataSource.
Expected output is as below.
const data = [
{
key: '1',
name: 'Andregan',
resultCount: 3,
resultIds: [16, 17, 21],
children: [
{
key: '21',
name: 'Silk',
resultCount: 2,
resultIds: [16, 17, 21],
children: [
{
key: '234',
name: 'Meegan',
resultCount: 2,
resultIds: [16, 17],
children: [
{
key: '41',
name: 'Thumphil',
resultCount: 2,
resultIds: [16, 17],
},
],
},
{
key: '44',
name: 'Wrens',
resultCount: 1,
resultIds: [21],
children: [
{
key: '49',
name: 'Cardin',
resultCount: 1,
resultIds: [21],
},
],
},
],
},
],
},
{
key: '2',
name: 'Kiren',
resultCount: 1,
resultIds: [18],
children: [
{
key: '23',
name: 'Georgia',
resultCount: 1,
resultIds: [18],
children: [
{
key: '34',
name: 'Eden Hill',
resultCount: 1,
resultIds: [18],
children: [
{
key: '99',
name: 'Southern Sea',
resultCount: 1,
resultIds: [18],
},
],
},
],
},
],
},
];
Can anyone suggest how to format response to above format to achieve this? Thank you.

How to remove all empty array childrens [] from a nested JSON recursively [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I've a JSON response as below.I'm using nested JSON data from my GeoRegionCountries APIController & custom class TreeView is used to format the data as per the required nested structure of plugin I'm using. I am using a combo multi select Treeview using this jquery plugin Multi-Select Drop Down Tree Plugin you can see it by this link jquery plugin Multi-Select Drop Down Tree Plugin
[
{
"Id": 1,
"Title": "United States",
"ParentId": null,
"Subs": [
{
"Id": 7,
"Title": "Northwest",
"ParentId": 1,
"Subs": []
},
{
"Id": 8,
"Title": "Northeast",
"ParentId": 1,
"Subs": []
},
{
"Id": 9,
"Title": "Central",
"ParentId": 1,
"Subs": []
},
{
"Id": 10,
"Title": "Southwest",
"ParentId": 1,
"Subs": []
},
{
"Id": 18,
"Title": "Southeast",
"ParentId": 1,
"Subs": []
}
]
},
{
"Id": 2,
"Title": "Canada",
"ParentId": null,
"Subs": []
},
{
"Id": 3,
"Title": "France",
"ParentId": null,
"Subs": []
},
{
"Id": 4,
"Title": "Germany",
"ParentId": null,
"Subs": []
},
{
"Id": 5,
"Title": "Australia",
"ParentId": null,
"Subs": []
},
{
"Id": 6,
"Title": "United Kingdom",
"ParentId": null,
"Subs": []
}
]
I want to remove all "Subs" with empty array.
[
{
"Id": 1,
"Title": "United States",
"ParentId": null,
"Subs": [
{
"Id": 7,
"Title": "Northwest",
"ParentId": 1
},
{
"Id": 8,
"Title": "Northeast",
"ParentId": 1
},
{
"Id": 9,
"Title": "Central",
"ParentId": 1
},
{
"Id": 10,
"Title": "Southwest",
"ParentId": 1
},
{
"Id": 18,
"Title": "Southeast",
"ParentId": 1
}
]
},
{
"Id": 2,
"Title": "Canada",
"ParentId": null
},
{
"Id": 3,
"Title": "France",
"ParentId": null
},
{
"Id": 4,
"Title": "Germany",
"ParentId": null
},
{
"Id": 5,
"Title": "Australia",
"ParentId": null
},
{
"Id": 6,
"Title": "United Kingdom",
"ParentId": null
}
]
What is the best way to deep clean this? I tried different solutions in Stackopverflow but all i got is Object object in place of empty Subs - which i don't want.
[
{
"Id": 1,
"Title": "United States",
"ParentId": null,
"Subs": [
{
"Id": 7,
"Title": "Northwest",
"ParentId": 1,
Object object
},
{
"Id": 8,
"Title": "Northeast",
"ParentId": 1,
Object object
},
{
"Id": 9,
"Title": "Central",
"ParentId": 1,
Object object
},
{
"Id": 10,
"Title": "Southwest",
"ParentId": 1,
Object object
},
{
"Id": 18,
"Title": "Southeast",
"ParentId": 1,
Object object
}
]
},
{
"Id": 2,
"Title": "Canada",
"ParentId": null,
Object object
},
{
"Id": 3,
"Title": "France",
"ParentId": null,
Object object
},
{
"Id": 4,
"Title": "Germany",
"ParentId": null,
Object object
},
{
"Id": 5,
"Title": "Australia",
"ParentId": null,
Object object
},
{
"Id": 6,
"Title": "United Kingdom",
"ParentId": null,
Object object
}
]
which is not i want
You can use _.transform() to recursively check for a specific key (Subs), and remove it if it's value is empty:
const { transform, isObject, isEmpty } = _;
const removeEmpty = (obj, key) =>
transform(obj, (r, v, k) => {
if(k === key && isEmpty(v)) return;
r[k] = isObject(v) ? removeEmpty(v, key) : v;
});
const tree = [{"Id":1,"Title":"United States","ParentId":null,"Subs":[{"Id":7,"Title":"Northwest","ParentId":1,"Subs":[]},{"Id":8,"Title":"Northeast","ParentId":1,"Subs":[]},{"Id":9,"Title":"Central","ParentId":1,"Subs":[]},{"Id":10,"Title":"Southwest","ParentId":1,"Subs":[]},{"Id":18,"Title":"Southeast","ParentId":1,"Subs":[]}]},{"Id":2,"Title":"Canada","ParentId":null,"Subs":[]},{"Id":3,"Title":"France","ParentId":null,"Subs":[]},{"Id":4,"Title":"Germany","ParentId":null,"Subs":[]},{"Id":5,"Title":"Australia","ParentId":null,"Subs":[]},{"Id":6,"Title":"United Kingdom","ParentId":null,"Subs":[]}]
const result = removeEmpty(tree, 'Subs');
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>
The correct answer would be this:
let array = [
{
'Id': 1,
'Title': 'United States',
'ParentId': null,
'Subs': [
{
'Id': 7,
'Title': 'Northwest',
'ParentId': 1,
'Subs': []
},
{
'Id': 8,
'Title': 'Northeast',
'ParentId': 1,
'Subs': []
},
{
'Id': 9,
'Title': 'Central',
'ParentId': 1,
'Subs': []
},
{
'Id': 10,
'Title': 'Southwest',
'ParentId': 1,
'Subs': []
},
{
'Id': 18,
'Title': 'Southeast',
'ParentId': 1,
'Subs': []
}
]
},
{
'Id': 2,
'Title': 'Canada',
'ParentId': null,
'Subs': []
},
{
'Id': 3,
'Title': 'France',
'ParentId': null,
'Subs': []
},
{
'Id': 4,
'Title': 'Germany',
'ParentId': null,
'Subs': []
},
{
'Id': 5,
'Title': 'Australia',
'ParentId': null,
'Subs': []
},
{
'Id': 6,
'Title': 'United Kingdom',
'ParentId': null,
'Subs': []
}
]
let newArray = array.map(item=> {
if (item.Subs.length===0){
delete item.Subs
return item
}
item.Subs = item.Subs.map(item=>{
if (item.Subs.length===0){
delete item.Subs
return item
}
})
return item
}
)
console.log(newArray)
let data = [
{
"Id": 1,
"Title": "United States",
"ParentId": null,
"Subs": [
{
"Id": 7,
"Title": "Northwest",
"ParentId": 1,
"Subs": []
},
{
"Id": 8,
"Title": "Northeast",
"ParentId": 1,
"Subs": []
},
{
"Id": 9,
"Title": "Central",
"ParentId": 1,
"Subs": []
},
{
"Id": 10,
"Title": "Southwest",
"ParentId": 1,
"Subs": []
},
{
"Id": 18,
"Title": "Southeast",
"ParentId": 1,
"Subs": []
}
]
},
{
"Id": 2,
"Title": "Canada",
"ParentId": null,
"Subs": []
},
{
"Id": 3,
"Title": "France",
"ParentId": null,
"Subs": []
},
{
"Id": 4,
"Title": "Germany",
"ParentId": null,
"Subs": []
},
{
"Id": 5,
"Title": "Australia",
"ParentId": null,
"Subs": []
},
{
"Id": 6,
"Title": "United Kingdom",
"ParentId": null,
"Subs": []
}
];
data = data.map(row=>{
if (!row.Subs.length) {
let {Subs,...r} = row;
return r;
} return row
})
console.log(data);
write two functions and pass the function that iterates through your array to a map function on data as shown below
function formatData(val) {
if (val.Subs.length > 0) val.Subs.map(a => a.Subs.length > 0 ? formatData(a.Subs) : deleteSubs(a));
else deleteSubs(val);
return val;
}
function deleteSubs(val) {
delete val.Subs;
}
var data = [{
"Id": 1,
"Title": "United States",
"ParentId": null,
"Subs": [{
"Id": 7,
"Title": "Northwest",
"ParentId": 1,
"Subs": []
},
{
"Id": 8,
"Title": "Northeast",
"ParentId": 1,
"Subs": []
},
{
"Id": 9,
"Title": "Central",
"ParentId": 1,
"Subs": []
},
{
"Id": 10,
"Title": "Southwest",
"ParentId": 1,
"Subs": []
},
{
"Id": 18,
"Title": "Southeast",
"ParentId": 1,
"Subs": []
}
]
},
{
"Id": 2,
"Title": "Canada",
"ParentId": null,
"Subs": []
},
{
"Id": 3,
"Title": "France",
"ParentId": null,
"Subs": []
},
{
"Id": 4,
"Title": "Germany",
"ParentId": null,
"Subs": []
},
{
"Id": 5,
"Title": "Australia",
"ParentId": null,
"Subs": []
},
{
"Id": 6,
"Title": "United Kingdom",
"ParentId": null,
"Subs": []
}
]
console.log(data.map(formatData))

Add a property to grouped objects and ungroup

I'm using underscore.js to group my objects, now I want to add a property to work as an identifier for that group and then reduce those objects back into its original structure. But not sure how to do it.
The rule is to find who has more than one appointment in that day and add a property to it.
Something we achieved here:
https://jsfiddle.net/bjxgszmw/
with this line of code:
var resultt = _.chain(allAppointments)
.groupBy('appointment_date')
.mapObject( date => _.groupBy(date, 'email' ) )
So from what we have've got which is this:
{
"23July": {
"john#domain.com": [
{
"ap_id": 23,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 3,
"time": "morning"
},
{
"ap_id": 44,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
}
],
"rose#domain.com": [
{
"ap_id": 55,
to something simple like this;
allAppointments_Filtered:
[{
"ap_id": 23,
"name": "John",
"email": "John#domain.com",
"appointment_date": "23July",
"appointment_category": 3,
"time": "morning",
hasMultipleAppointmentOnDate: "yes"
},{
"ap_id": 55,
"name": "Rose",
"email": "rose#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternoon"
hasMultipleAppointmentOnDate: "nope"
},{
"ap_id": 44,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternoon"
hasMultipleAppointmentOnDate: "yes"
},{
...
}];
Well, you don't need to do all those grouping and mappings. All you have to do is a single map and a count based on the current appointment you check:
var allAppointments = [
{
"ap_id": 23,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 3,
"time": "morning"
},
{
"ap_id": 55,
"name": "Rose",
"email": "rose#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
},
{
"ap_id": 44,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
},
{
"ap_id": 70,
"name": "Kate",
"email": "kate#domain.com",
"appointment_date": "29July",
"appointment_category": 4,
"time": "afternon"
}
]
var counts = {};
var result = _.mapObject(allAppointments, (appointment) => {
var key = appointment.email + appointment.appointment_date;
if (!_.has(counts, key)) {
counts[key] = _.countBy(allAppointments, (app) =>
appointment.email === app.email &&
appointment.appointment_date === app.appointment_date
).true > 1
}
appointment.hasMultipleAppointmentOnDate = counts[key];
return appointment;
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
You need to group by a composite key:
// data
const allAppointments = [
{
"ap_id": 23,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 3,
"time": "morning"
},
{
"ap_id": 55,
"name": "Rose",
"email": "rose#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
},
{
"ap_id": 44,
"name": "John",
"email": "john#domain.com",
"appointment_date": "23July",
"appointment_category": 4,
"time": "afternon"
},
{
"ap_id": 70,
"name": "Kate",
"email": "kate#domain.com",
"appointment_date": "29July",
"appointment_category": 4,
"time": "afternon"
}
];
// gets grouping key, which is email + date
const groupKey = i => i.email +'_'+ i.appointment_date;
// store counts for appointments for unique (email + date)
const counts = _.countBy(allAppointments,groupKey);
// checks if appointment has more than one instances on date
const isMulti = i => counts[groupKey(i)] > 1;
// updated appointment with multiple indicator property
const multiProp = i => ({hasMultipleAppointmentOnDate: isMulti(i) ? "yes": "nope"});
// update initial array items with multiple
const updated = _.map(allAppointments,i => _.extend(i,multiProp(i)));
// see results
console.log(updated);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>

Formatting a JSON data using lodash [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 6 years ago.
I have a JSON data with the following format:
activities
[
{
"id": 32,
"poi_id": 1,
"due_date": "2016-09-08T18:15:00.000Z",
"items": [
{
"id": 21,
"name": "Choluv jar : JAR",
"activity_id": 32
}
]
},
{
"id": 30,
"poi_id": 9,
"due_date": "2016-09-14T18:15:00.000Z",
"items": [
{
"id": 17,
"name": "Bourbon Family : PKT",
"activity_id": 30
},
{
"id": 18,
"name": "Choluv jar : JAR",
"activity_id": 30
}
]
},
{
"id": 29,
"poi_id": 1,
"due_date": "2016-09-27T18:15:00.000Z",
"items": [
{
"id": 16,
"name": "Choluv jar : JAR",
"activity_id": 29
}
]
}
]
I want to reformat this data using lodash or simply javascript to look like this:
/*poi_id is the key*/
"1": [{
"id": 32,
"poi_id": 1,
"due_date": "2016-09-08T18:15:00.000Z",
"items": {
/*due_date is the key*/
"2016-09-08T18:15:00.000Z": [{
"id": 21,
"name": "Choluv jar : JAR",
"activity_id": 32
}]
}
}, {
"id": 29,
"poi_id": 1,
"due_date": "2016-09-27T18:15:00.000Z",
"items": {
"2016-09-27T18:15:00.000Z": [{
"id": 16,
"name": "Choluv jar : JAR",
"activity_id": 29
}]
}
}],
"9": [{
"id": 30,
"poi_id": 9,
"due_date": "2016-09-14T18:15:00.000Z",
"items": {
"2016-09-14T18:15:00.000Z": [{
"id": 17,
"name": "Bourbon Family : PKT",
"activity_id": 30
}, {
"id": 18,
"name": "Choluv jar : JAR",
"activity_id": 30
}]
}
}]
All I want is to put the data that has the same poi_id under one collection with the key of poi_id and same for the items with same due_date.
Here's what I've done so far:
let activityArray = {};
_.forEach(activities, (activityItem) => {
if (!activityArray[activityItem.poi_id]) {
activityArray[activityItem.poi_id] = [];
}
activityArray[activityItem.poi_id].push(activityItem);
_.forEach(activityArray[activityItem.poi_id], (value, key) => {
activityArray[activityItem.poi_id][key].items.unshift(activityArray[activityItem.poi_id][key].due_date);
});
});
And this is what I got:
"1": [{
"id": 32,
"poi_id": 1,
"due_date": "2016-09-08T18:15:00.000Z",
/*unShift added due_date twice here, I want here key value pair*/
"items": [
"2016-09-08T18:15:00.000Z",
"2016-09-08T18:15:00.000Z", {
"id": 21,
"name": "Choluv jar : JAR",
"activity_id": 32
}
]
}, {
"id": 29,
"poi_id": 1,
"due_date": "2016-09-27T18:15:00.000Z",
"items": [
"2016-09-27T18:15:00.000Z", {
"id": 16,
"name": "Choluv jar : JAR",
"activity_id": 29
}
]
}],
"9": [{
"id": 30,
"poi_id": 9,
"due_date": "2016-09-14T18:15:00.000Z",
"items": [
"2016-09-14T18:15:00.000Z", {
"id": 17,
"name": "Bourbon Family : PKT",
"activity_id": 30
}, {
"id": 18,
"name": "Choluv jar : JAR",
"activity_id": 30
}
]
}]
I tried with other approaches too, but couldn't make it like the one I'm expecting.
Please guide me here.
Thanks.
A compact solution in plain Javascript with an object as hash for the items arrays.
var activities = [{ "id": 32, "poi_id": 1, "due_date": "2016-09-08T18:15:00.000Z", "items": [{ "id": 21, "name": "Choluv jar : JAR", "activity_id": 32 }] }, { "id": 30, "poi_id": 9, "due_date": "2016-09-14T18:15:00.000Z", "items": [{ "id": 17, "name": "Bourbon Family : PKT", "activity_id": 30 }, { "id": 18, "name": "Choluv jar : JAR", "activity_id": 30 }] }, { "id": 29, "poi_id": 1, "due_date": "2016-09-27T18:15:00.000Z", "items": [{ "id": 16, "name": "Choluv jar : JAR", "activity_id": 29 }] }],
hash = {},
grouped = {};
activities.forEach(a => {
hash[a.poi_id] = hash[a.poi_id] || {};
hash[a.poi_id][a.due_date] = hash[a.poi_id][a.due_date] || [];
grouped[a.poi_id] = grouped[a.poi_id] || [];
grouped[a.poi_id].push({
id: a.id,
poi_id: a.poi_id,
due_date: a.due_date,
items: { [a.due_date]: hash[a.poi_id][a.due_date] }
});
a.items.forEach(b => hash[a.poi_id][a.due_date].push(b));
});
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Categories