简体   繁体   中英

JavaScript recursive function to transform parent/child records into a nested array

I have a Json array, which is structured perfectly for a Kendo treelist widget (ie very simple treelist example treelist ); however, I now need to render the same data in a Kendo treemap widget.

So, the source data is flat and contains both an id and parentId field. I now need to recursively visit each node and transform this into a nested array.

I've started a plunk which contains the flat source data (filename is "sourcedata.json"), as well as sample target data ("treedata.json") which currently renders a Kendo treemap if you run the plunk.

 http://plnkr.co/edit/Cmfk8YWdm0uPrdDiJIfC?p=preview   

treemap data

Here's the source (fyi: "parentId": null is my root node) -

 [ { "id": 0, "parentId": 6, "typeId": 0, "field0": "London", "field2": 5546919.064936 }, { "id": 1, "parentId": 7, "typeId": 0, "field0": "New York", "field2": 2297941.24812 }, { "id": 2, "parentId": 5, "typeId": 0, "field0": "Dubai", "field2": 9832458.096596 }, { "id": 3, "parentId": 6, "typeId": 0, "field0": "Paris", "field2": 22700818.88167 }, { "id": 4, "parentId": 8, "typeId": 0, "field0": "Stockholm", "field2": 3742748.296602, }, { "id": 5, "parentId": 9, "typeId": 0, "field0": "Middle East", "field2": 9832458.096596, }, { "id": 6, "parentId": 9, "typeId": 0, "field0": "Europe", "field2": 31990486.243208, }, { "id": 7, "parentId": 9, "typeId": 0, "field0": "NorthAmerica", "field2": 2297941.24812, }, { "id": 8, "parentId": 6, "typeId": 0, "field0": "Scandinavia", "field2": 3742748.296602, }, { "id": 9, "parentId": null, "typeId": 0, "field0": "World", "field2": 44120885.587924, }, { "id": 10, "parentId": 0, "typeId": 1, "field0": "BOND-1001", "field2": 3985.331955, }, { "id": 28, "parentId": 0, "typeId": 1, "field0": "IRSW-08634", "field2": 10307.142591, }, { "id": 29, "parentId": 0, "typeId": 1, "field0": "IRSW-08639", "field2": 17116.371459, }, { "id": 58, "parentId": 0, "typeId": 1, "field0": "BOND-0013", "field2": 19029.816578, }, { "id": 59, "parentId": 0, "typeId": 1, "field0": "BOND-0031", "field2": -237.872707, }, { "id": 60, "parentId": 0, "typeId": 1, "field0": "BOND-0034", "field2": 859.61482, }, { "id": 61, "parentId": 0, "typeId": 1, "field0": "BOND-0037", "field2": 852.099758, }, { "id": 62, "parentId": 0, "typeId": 1, "field0": "BOND-0043", "field2": 4452.369428, "field4": 1 }, { "id": 63, "parentId": 0, "typeId": 1, "field0": "BOND-0046", "field2": -2226.184714, }, { "id": 64, "parentId": 0, "typeId": 1, "field0": "BOND-0049", "field2": 6612.946972, }, { "id": 65, "parentId": 0, "typeId": 1, "field0": "BOND-0050", "field2": 3844146.217229, }, { "id": 66, "parentId": 1, "typeId": 1, "field0": "BOND-1002", "field2": 3985.331955, }, { "id": 67, "parentId": 1, "typeId": 1, "field0": "BOND-1005", "field2": -2707.4266, }, { "id": 68, "parentId": 1, "typeId": 1, "field0": "BOND-1008", "field2": -2436.68394, }, { "id": 69, "parentId": 1, "typeId": 1, "field0": "BOND-1011", "field2": 683.959918, }, { "id": 70, "parentId": 1, "typeId": 1, "field0": "BOND-1014", "field2": 54716.79346, }, { "id": 71, "parentId": 1, "typeId": 1, "field0": "BOND-1017", "field2": 4027.155999, }, { "id": 72, "parentId": 1, "typeId": 1, "field0": "XCSW-0046", "field2": 604546.163294, "node2": 2, "field3": 498334.387729, "node3": 3, "field4": 1 }, { "id": 73, "parentId": 1, "typeId": 1, "field0": "IRSW-08655", "field2": 46191.801872, "node2": 2, "field3": 37131.473418, "node3": 3, "field4": 1 }, { "id": 74, "parentId": 1, "typeId": 1, "field0": "CF-0012", "field2": 1845434.652127, "node2": 2, "field3": 1438283.786114, "node3": 3, "field4": 1 }, { "id": 75, "parentId": 1, "typeId": 1, "field0": "CF-0017", "field2": 46486.869315, "node2": 2, "field3": 36285.674082, "node3": 3, "field4": 1 }, { "id": 76, "parentId": 1, "typeId": 1, "field0": "CF-0002", "field2": -593582.845166, "node2": 2, "field3": -402546.0446, "node3": 3, "field4": 1 }, { "id": 77, "parentId": 1, "typeId": 1, "field0": "CRSW-1002", "field2": -73496.275293, "node2": 2, "field3": -5325.413593, "node3": 3, "field4": 1 }, { "id": 78, "parentId": 1, "typeId": 1, "field0": "CRSW-1005", "field2": 20670.748989, "node2": 2, "field3": 27954.103116, "node3": 3, "field4": 1 }, { "id": 79, "parentId": 1, "typeId": 1, "field0": "CRSW-1008", "field2": 53572.838484, "node2": 2, "field3": 27688.010937, "node3": 3, "field4": 1 }, { "id": 80, "parentId": 1, "typeId": 1, "field0": "CRSW-1011", "field2": 58.44961, "node2": 2, "field3": 83.488679, "node3": 3, "field4": 1 }, { "id": 81, "parentId": 1, "typeId": 1, "field0": "CRSW-1014", "field2": -296158.053382, "node2": 2, "field3": -288493.393334, "node3": 3, "field4": 1 }, { "id": 82, "parentId": 1, "typeId": 1, "field0": "CRSW-1017", "field2": -21563.217578, "node2": 2, "field3": -20779.990677, "node3": 3, "field4": 1 }, { "id": 83, "parentId": 1, "typeId": 1, "field0": "LOAN-0012", "field2": -16809.368436, "node2": 2, "field3": -16401.910829, "node3": 3, "field4": 1 }, { "id": 84, "parentId": 1, "typeId": 1, "field0": "LOAN-0017", "field2": 10307.142591, "node2": 2, "field3": 9867.818502, "node3": 3, "field4": 1 }, { "id": 85, "parentId": 1, "typeId": 1, "field0": "FX-00342", "field2": 17116.371459, "node2": 2, "field3": 16382.149866, "node3": 3, "field4": 1 }, { "id": 86, "parentId": 1, "typeId": 1, "field0": "FX-00354", "field2": 3721.762854, "node2": 2, "field3": 3541.481944, "node3": 3, "field4": 1 }, { "id": 87, "parentId": 1, "typeId": 1, "field0": "FX-00406", "field2": 1479.737038, "node2": 2, "field3": 1408.059086, "node3": 3, "field4": 1 }, { "id": 88, "parentId": 1, "typeId": 1, "field0": "FX-00410", "field2": 4699.141795, "node2": 2, "field3": 4487.080289, "node3": 3, "field4": 1 }, { "id": 89, "parentId": 1, "typeId": 1, "field0": "FX-00418", "field2": 53.411383, "node2": 2, "field3": -25.478062, "node3": 3, "field4": 1 }, { "id": 90, "parentId": 1, "typeId": 1, "field0": "FX-00426", "field2": 1625.14897, "node2": 2, "field3": 2319.189521, "node3": 3, "field4": 1 }, { "id": 91, "parentId": 1, "typeId": 1, "field0": "FRA-0002", "field2": -4634.930756, "node2": 2, "field3": -6613.572492, "node3": 3, "field4": 1 }, { "id": 92, "parentId": 1, "typeId": 1, "field0": "FRA-0005", "field2": -7375.479672, "node2": 2, "field3": -17104.920999, "node3": 3, "field4": 1 }, { "id": 93, "parentId": 1, "typeId": 1, "field0": "FRA-0008", "field2": 0, "node2": 2, "field3": 0, "node3": 3, "field4": 1 }, { "id": 94, "parentId": 1, "typeId": 1, "field0": "FRA-0011", "field2": 125.281197, "node2": 2, "field3": 181.176247, "node3": 3, "field4": 1 }, { "id": 95, "parentId": 1, "typeId": 1, "field0": "FRA-0014", "field2": 95.900079, "node2": 2, "field3": 122.515322, "node3": 3, "field4": 1 }, { "id": 96, "parentId": 1, "typeId": 1, "field0": "BOND-0014", "field2": 35.094497, "node2": 2, "field3": 45.048084, "node3": 3, "field4": 1 }, { "id": 97, "parentId": 1, "typeId": 1, "field0": "BOND-0017", "field2": 42.085388, "node2": 2, "field3": 61.758662, "node3": 3, "field4": 1 }, { "id": 98, "parentId": 1, "typeId": 1, "field0": "BOND-0023", "field2": -1527.85633, "node2": 2, "field3": -7451.691034, "node3": 3, "field4": 1 }, { "id": 99, "parentId": 1, "typeId": 1, "field0": "BOND-0029", "field2": -10505.835091, "node2": 2, "field3": -43600.76525, "node3": 3, "field4": 1 }, { "id": 100, "parentId": 1, "typeId": 1, "field0": "BOND-0032", "field2": 0, "node2": 2, "field3": 0, "node3": 3, "field4": 1 }, { "id": 101, "parentId": 1, "typeId": 1, "field0": "BOND-0035", "field2": 8.385045, "node2": 2, "field3": 2967.079788, "node3": 3, "field4": 1 }, { "id": 102, "parentId": 1, "typeId": 1, "field0": "BOND-0041", "field2": 543.371559, "node2": 2, "field3": 29891.343594, "node3": 3, "field4": 1 }, { "id": 103, "parentId": 1, "typeId": 1, "field0": "BOND-0044", "field2": 73.610827, "node2": 2, "field3": 5960.758206, "node3": 3, "field4": 1 }, { "id": 104, "parentId": 1, "typeId": 1, "field0": "BOND-0047", "field2": 894.247491, "node2": 2, "field3": 15292.150889, "node3": 3, "field4": 1 }, { "id": 105, "parentId": 2, "typeId": 1, "field0": "BOND-1003", "field2": 3985.331955, "node2": 2, "field3": 20567.245997, "node3": 3, "field4": 1 }, { "id": 106, "parentId": 2, "typeId": 1, "field0": "BOND-1006", "field2": -2707.4266, "node2": 2, "field3": -13972.313856, "node3": 3, "field4": 1 }, { "id": 107, "parentId": 2, "typeId": 1, "field0": "BOND-1009", "field2": -2436.68394, "node2": 2, "field3": -12575.082471, "node3": 3, "field4": 1 }, { "id": 108, "parentId": 2, "typeId": 1, "field0": "BOND-1012", "field2": 683.959918, "node2": 2, "field3": 3527.163486, "node3": 3, "field4": 1 }, { "id": 109, "parentId": 2, "typeId": 1, "field0": "BOND-1015", "field2": 54716.79346, "node2": 2, "field3": 282173.078874, "node3": 3, "field4": 1 }, { "id": 110, "parentId": 2, "typeId": 1, "field0": "XCSW-0004", "field2": 4027.155999, "node2": 2, "field3": 20767.938605, "node3": 3, "field4": 1 }, { "id": 111, "parentId": 2, "typeId": 1, "field0": "XCSW-0014", "field2": 604546.163294, "node2": 2, "field3": 498334.387729, "node3": 3, "field4": 1 }, { "id": 112, "parentId": 2, "typeId": 1, "field0": "XCSW-0017", "field2": 46191.801872, "node2": 2, "field3": 37131.473418, "node3": 3, "field4": 1 }, { "id": 113, "parentId": 2, "typeId": 1, "field0": "XCSW-0029", "field2": 1845434.652127, "node2": 2, "field3": 1438283.786114, "node3": 3, "field4": 1 }, { "id": 114, "parentId": 2, "typeId": 1, "field0": "XCSW-0034", "field2": 46486.869315, "node2": 2, "field3": 36285.674082, "node3": 3, "field4": 1 }, { "id": 115, "parentId": 2, "typeId": 1, "field0": "XCSW-0045", "field2": -593582.845166, "node2": 2, "field3": -402546.0446, "node3": 3, "field4": 1 }, { "id": 116, "parentId": 2, "typeId": 1, "field0": "XCSW-0053", "field2": -73496.275293, "node2": 2, "field3": -5325.413593, "node3": 3, "field4": 1 }, { "id": 117, "parentId": 2, "typeId": 1, "field0": "XCSW-0072", "field2": 20670.748989, "node2": 2, "field3": 27954.103116, "node3": 3, "field4": 1 }, { "id": 118, "parentId": 2, "typeId": 1, "field0": "IRSW-00022", "field2": 53572.838484, "node2": 2, "field3": 27688.010937, "node3": 3, "field4": 1 }, { "id": 119, "parentId": 2, "typeId": 1, "field0": "IRSW-00030", "field2": 58.44961, "node2": 2, "field3": 83.488679, "node3": 3, "field4": 1 }, { "id": 120, "parentId": 2, "typeId": 1, "field0": "IRSW-00037", "field2": -296158.053382, "node2": 2, "field3": -288493.393334, "node3": 3, "field4": 1 }, { "id": 121, "parentId": 2, "typeId": 1, "field0": "IRSW-00042", "field2": -21563.217578, "node2": 2, "field3": -20779.990677, "node3": 3, "field4": 1 }, { "id": 122, "parentId": 2, "typeId": 1, "field0": "IRSW-04172", "field2": -16809.368436, "node2": 2, "field3": -16401.910829, "node3": 3, "field4": 1 }, { "id": 123, "parentId": 2, "typeId": 1, "field0": "IRSW-04177", "field2": 10307.142591, "node2": 2, "field3": 9867.818502, "node3": 3, "field4": 1 }, { "id": 124, "parentId": 2, "typeId": 1, "field0": "IRSW-04182", "field2": 17116.371459, "node2": 2, "field3": 16382.149866, "node3": 3, "field4": 1 }, { "id": 125, "parentId": 2, "typeId": 1, "field0": "IRSW-04185", "field2": 3721.762854, "node2": 2, "field3": 3541.481944, "node3": 3, "field4": 1 }, { "id": 126, "parentId": 2, "typeId": 1, "field0": "IRSW-04192", "field2": 1479.737038, "node2": 2, "field3": 1408.059086, "node3": 3, "field4": 1 }, { "id": 127, "parentId": 2, "typeId": 1, "field0": "IRSW-08627", "field2": 4699.141795, "node2": 2, "field3": 4487.080289, "node3": 3, "field4": 1 }, { "id": 128, "parentId": 2, "typeId": 1, "field0": "IRSW-08632", "field2": 53.411383, "node2": 2, "field3": -25.478062, "node3": 3, "field4": 1 }, { "id": 129, "parentId": 2, "typeId": 1, "field0": "IRSW-08637", "field2": 1625.14897, "node2": 2, "field3": 2319.189521, "node3": 3, "field4": 1 }, { "id": 130, "parentId": 2, "typeId": 1, "field0": "IRSW-08642", "field2": -4634.930756, "node2": 2, "field3": -6613.572492, "node3": 3, "field4": 1 }, { "id": 131, "parentId": 2, "typeId": 1, "field0": "IRSW-08647", "field2": -7375.479672, "node2": 2, "field3": -17104.920999, "node3": 3, "field4": 1 }, { "id": 132, "parentId": 2, "typeId": 1, "field0": "IRSW-08650", "field2": 0, "node2": 2, "field3": 0, "node3": 3, "field4": 1 }, { "id": 133, "parentId": 2, "typeId": 1, "field0": "IRSW-08652", "field2": 125.281197, "node2": 2, "field3": 181.176247, "node3": 3, "field4": 1 }, { "id": 134, "parentId": 2, "typeId": 1, "field0": "IRSW-08657", "field2": 95.900079, "node2": 2, "field3": 122.515322, "node3": 3, "field4": 1 }, { "id": 135, "parentId": 2, "typeId": 1, "field0": "CF-0004", "field2": 35.094497, "node2": 2, "field3": 45.048084, "node3": 3, "field4": 1 }, { "id": 136, "parentId": 2, "typeId": 1, "field0": "CF-0014", "field2": 42.085388, "node2": 2, "field3": 61.758662, "node3": 3, "field4": 1 }, { "id": 137, "parentId": 2, "typeId": 1, "field0": "CF-0024", "field2": -1527.85633, "node2": 2, "field3": -7451.691034, "node3": 3, "field4": 1 }, { "id": 138, "parentId": 2, "typeId": 1, "field0": "CF-0029", "field2": -10505.835091, "node2": 2, "field3": -43600.76525, "node3": 3, "field4": 1 }, { "id": 139, "parentId": 2, "typeId": 1, "field0": "CF-0009", "field2": 0, "node2": 2, "field3": 0, "node3": 3, "field4": 1 }, { "id": 140, "parentId": 2, "typeId": 1, "field0": "CRSW-1003", "field2": 8.385045, "node2": 2, "field3": 2967.079788, "node3": 3, "field4": 1 }, { "id": 141, "parentId": 2, "typeId": 1, "field0": "CRSW-1006", "field2": 543.371559, "node2": 2, "field3": 29891.343594, "node3": 3, "field4": 1 }, { "id": 142, "parentId": 2, "typeId": 1, "field0": "CRSW-1009", "field2": 73.610827, "node2": 2, "field3": 5960.758206, "node3": 3, "field4": 1 }, { "id": 143, "parentId": 2, "typeId": 1, "field0": "CRSW-1012", "field2": 894.247491, "node2": 2, "field3": 15292.150889, "node3": 3, "field4": 1 }, { "id": 144, "parentId": 2, "typeId": 1, "field0": "CRSW-1015", "field2": 1788.494983, "node2": 2, "field3": 30584.301778, "node3": 3, "field4": 1 }, { "id": 145, "parentId": 2, "typeId": 1, "field0": "LOAN-0004", "field2": 1788.494983, "node2": 2, "field3": 30584.301778, "node3": 3, "field4": 1 }, { "id": 146, "parentId": 2, "typeId": 1, "field0": "LOAN-0014", "field2": -1346.424043, "node2": 2, "field3": 2340.573474, "node3": 3, "field4": 1 }, { "id": 147, "parentId": 2, "typeId": 1, "field0": "LOAN-0029", "field2": -1349.527119, "node2": 2, "field3": 2335.6426, "node3": 3, "field4": 1 }, { "id": 148, "parentId": 2, "typeId": 1, "field0": "CSA-3-1", "field2": 16116.217709, "node2": 2, "field3": 6028.837728, "node3": 3, "field4": 1 }, { "id": 149, "parentId": 2, "typeId": 1, "field0": "CSA-5-1", "field2": -144675.967051, "node2": 2, "field3": -52043.568419, "node3": 3, "field4": 1 }, { "id": 150, "parentId": 2, "typeId": 1, "field0": "CSA-10-1", "field2": 302407.68631, "node2": 2, "field3": 109564.416581, "node3": 3, "field4": 1 }, { "id": 151, "parentId": 2, "typeId": 1, "field0": "CSA-101-1", "field2": -189203.37048, "node2": 2, "field3": -69223.41632, "node3": 3, "field4": 1 }, { "id": 152, "parentId": 2, "typeId": 1, "field0": "CSA-4-1", "field2": -955.127578, "node2": 2, "field3": -898.382846, "node3": 3, "field4": 1 }, { "id": 230, "parentId": 4, "typeId": 1, "field0": "LOAN-0030", "field2": 4699.141795 } ] 

and the target data needs to have this nested array structure:

 [ { "name": "HSVaR 1D 99%, By Location", "value":44120885.587924, "items":[ { "name":"NorthAmerica", "value": 2297941.24812, "items":[ { "name":"New York", "value":2297941.24812 } ] }, { "name":"Europe", "value":31990486.243208, "items":[ { "name":"London", "value":5546919.06 }, { "name":"Paris", "value":22700818.88167 }, { "name":"Scandinavia", "value":3742748.296602 } ] }, { "name":"Middle East", "value":2959373, "items":[ { "name":"Dubai", "value":9832458.096596 } ] } ] } ] 

* UPDATE: FINAL WORKING VERSION - Same nested results as the gentleman who answered below with a non-recursive routine *

 function parseTreeMapData(data) { // init new array, find root node var newJson = []; var root = _.findWhere(data, { parentId: null }); // recurse data, starting with root node; pass in empty array newJson = recurseTreeMapData(data, root, []); var top = []; top.push({ root.field0, value: root.field2, items: newJson.items }); return top; } function recurseTreeMapData(data, root, newData) { // passing in the root node, get children, recurse until leaf is reached. var child = _.where(data, { parentId: root.id }); if (child.length > 0) { if (!newData.items){ newData.items = []; } for (var i = 0; i < child.length; i++){ newData.items.push( { id: child[i].id, parentId: child[i].parentId, name: child[i].field0, value: child[i].field2 }); // recursve with current child record recurseTreeMapData(data, child[i], newData.items[i]); } } return newData; } 

Thank you in advance,

Bob

I've edited your plunk and I think I've got the data right here although the treemap doesn't look right.

The algorithm I used was to first create a map from data IDs to data elements in the new format. Then I walk through the data again and add each data element to its parent's items array. Since these are all references we're mutating things in place and there's no need for topological sorting or anything.

I didn't find the need for recursion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM