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...
/*--------------------------------------------------------*\
| 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.
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