Search code examples
javascriptarrayskendo-treeview

Parse a nested array objects, and create a new array


I have a nested array of objects that I am parsing in JavaScript, but I'm having difficulty creating the target array.

Here's the properly-rendered Kendo UI treeview with a sample array attached to it (i.e. the way the final dataSource array should look like):

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

Kendo UI treeview widget

My source array has nested "children" arrays, where the leaf node is the "drms" array.

As I parse the nested children, I am trying to do the following :

  1. the non-empty "children" array needs to be renamed to "drms"
  2. the empty "children" array needs to be deleted

Here is a sample source array:

[	/* SOURCE ARRAY */
    {
        "category": "Market Risk",
        "sysid": 1,
        "children": [
            {
                "category": "General",
                "sysid": 2,
                "children": [],
                "drms": [
                    {
                        "name": "1 Day VaR (99%)"
                    },
                    {
                        "name": "10 Day VaR (99%)"
                    }
                ]
            },
            {
                "category": "Decomposition",
                "sysid": 3,
                "children": [],
                "drms": [
                    {
                        "name": "1D VaR Credit"                     
                    },
                    {
                        "name": "1D VaR Equity"
                    }
                ]
            },
            {
                "category": "Sensitivities",
                "sysid": 4,
                "children": [
                    {
                        "category": "Currency Pairs",
                        "sysid": 11,
                        "children": [
                            {
                                "category": "EUR/USD",
                                "sysid": 12,
                                "children": [],
                                "drms": [
                                    {
                                        "name": "Spot"                                      
                                    },
                                    {
                                        "name": "Spot - 0.01"                                       
                                    }                                    
                                ]
                            }
                        ],
                        "drms": []
                    }
                ],
                "drms": []
            }
        ],
        "drms": []
    },
    {
        "category": "CCR",
        "sysid": 6,
        "children": [
            {
                "category": "General (CCR)",
                "sysid": 7,
                "children": [],
                "drms": [
                    {
                        "name": "MTM"                       
                    },
                    {
                        "name": "PFE"                        
                    }
                ]
            }
        ],
        "drms": []
    }    
]

and the target array which I've modified manually in order to render the Kendo TreeView :

[		
      {
          "category": "Market Risk",
          "sysid": 1,
          "drms": [
              {
                  "category": "General",
                  "sysid": 2,
                  
                  "drms": [
                      {
                          "name": "1 Day VaR (99%)",
                          "riskMeasure": "-PERCENTILE(SUM([99_HSVaR]:[1D]),1)",
                          "cubeVector": "[99_HSVaR]:[1D]"
                      },
                      {
                          "name": "10 Day VaR (99%)",
                          "riskMeasure": "-PERCENTILE(SUM([99_HSVaR]:[2W]),1)",
                          "cubeVector": "[99_HSVaR]:[2W]"
                      },
                      {
                          "name": "Day over Day VaR",
                          "riskMeasure": "-PERCENTILE(SUM(today),1)+PERCENTILE(SUM(yesterday),1)",
                          "cubeVector": "[BASELINE]:[99_HSVaR]:[2W] as today, [BASELINE-1]:[99_HSVaR]:[2W] as yesterday"
                      }
                  ]
              },
              {
                  "category": "Decomposition",
                  "sysid": 3,
                  "drms": [
                      {
                          "name": "1D VaR Credit",
                          "riskMeasure": "SUM([99_HSVaR]:[1D CR])",
                          "cubeVector": "[99_HSVaR]:[1D CR]"
                      },
                      {
                          "name": "1D VaR Equity",
                          "riskMeasure": "SUM([99_HSVaR]:[1D EQ])",
                          "cubeVector": "[99_HSVaR]:[1D EQ]"
                      }
                  ]
              },
              {
                  "category": "Sensitivities",
                  "sysid": 4,
                  "drms": [
                      {
                          "category": "Currency Pairs",
                          "sysid": 11,
                          "drms": [
                              {
                                  "category": "EUR/USD",
                                  "sysid": 12,
                                  "children": [],
                                  "drms": [
                                      {
                                          "name": "Spot",
                                          "riskMeasure": "SUM([EUR_USD by EUR]:[Spot - 0.00])",
                                          "cubeVector": "[EUR_USD by EUR]:[Spot - 0.00]"
                                      },
                                      {
                                          "name": "Spot - 0.01",
                                          "riskMeasure": "SUM([EUR_USD by EUR]:[Spot - 0.01])",
                                          "cubeVector": "[EUR_USD by EUR]:[Spot - 0.01]"
                                      }
                                  ]
                              }
                          ],
                      }
                  ]
              }
          ],
      },
      {
          "category": "CCR",
          "sysid": 6,
          "drms": [
              {
                  "category": "General (CCR)",
                  "sysid": 7,
                  
                  "drms": [
                      {
                          "name": "MTM",
                          "riskMeasure": "SUM(MTM:MTM)",
                          "cubeVector": "MTM:MTM"
                      },
                      {
                          "name": "PFE",
                          "riskMeasure": "PERCENTILE(SUM(x),95)",
                          "cubeVector": "[Simulated]:[MCS] IF value > 0 as x"
                      }
                  ]
              }
          ]
      }
    ]

and my JavaScript routine which is not quite working yet. A bit of confusion while parsing the nested children:

function create_TempDrmTree() {
            // convert raw def risk measures (drm) data into a tree format for the Kendo treeview widget.
            var data = getTestDrmTree();

            var drmsJson = [];
            var i = 0;
            _.each(data, function (item) {
                drmsJson.push({ "category": item.category, drms: [] });
                if (item.children.length > 0) {
                    pushDrms(item.children);
                }
                i++;
            });
            
            function pushDrms(children) {
                _.each(children, function (item) {
                    if (item.children.length > 0) {
                        pushDrms(item.children);
                    }
                    else {
                        // no more children, so get the DRMs from item
                        // leaving tempty children[] causes an issue on Kendo treeview
                        delete item.children;   
                        drmsJson[i]["drms"] = item;
                    }
                });
            }

            return drmsJson;
        }


Solution

  • Based on your original idea, I modified it slightly. This works perfectly for my scenario.

    EDITED: from What is the most efficient way to clone an object?, we can easily create a brand new array and keep original one untouched.

    function parseDrmTree(items, isCloned) {
    
        if (isCloned !== true) {
            // Create json string from original item, and then parse it.
            // And only do this at the root.
            items = JSON.parse(JSON.stringify(items));
            isCloned = true;
        }
        // reparse the DRM source tree, renaming "children" array to "drms".
        items.forEach(function (item, index) {
            if (item.children.length > 0) {
                // copy children[] to  drms[]
                item.drms = parseDrmTree(item.children, isCloned);
            }                
            // children[] is empty; drms[] exist at this level
            delete item.children;
        }, this);
        return items;
    }
    

    You don't have to give an isCloned value, just input the target array, the function will create a brand new array, and use it to create the desired structure, and the origin one is untouched.