0

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;
        }
bob.mazzo
  • 5,183
  • 23
  • 80
  • 149
  • Is it possible that both `drms` and `children` contains items? – fuyushimoya Jun 22 '15 at 15:52
  • @fuyushimoya - No, that is NOT possible. Once the `children` array has a zero length, I am done. I can safely grab the `drms` leaf node. – bob.mazzo Jun 22 '15 at 15:54
  • Before I run into bed, let us do some little examination... 1. `sysid` is not preserved in root, as you pushed object don't have that. 2. In `pushDrms` your function keep deep down to see the leaf, but then, at the leaf, its behavior is assign the **last** children to its root's drms. So the structure just left with root and its last leaf. – fuyushimoya Jun 22 '15 at 19:00
  • Here I create a [jsFiddle](https://jsfiddle.net/6p9ypqt3/3/) for you with your code altered, it should work properly now. – fuyushimoya Jun 22 '15 at 19:09

1 Answers1

1

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.

Community
  • 1
  • 1
fuyushimoya
  • 9,715
  • 3
  • 27
  • 34
  • right. I see you're working on the source array, but I'll keep the return for clarity. – bob.mazzo Jun 22 '15 at 16:09
  • Oops, your `drms` always exist, but hide under `children`, I didn't notice that, need me to change my answer for a more simplified(But less general, in case that there DO have some item have both `drm` and `children`, or `drm` not exist case) version? – fuyushimoya Jun 22 '15 at 16:15
  • So if `children.length > 0` , then I need to call recursively. When `drms.length > 0` then I stop. – bob.mazzo Jun 22 '15 at 16:29
  • 1
    Yep, that's the idea, move `children` to `drms` if `children > 0`, stop and delete `drms` when `drms === 0` – fuyushimoya Jun 22 '15 at 16:31
  • Thank you again. I modified your original js routine just slightly, and it works perfectly for me. My original idea was to create a brand new array, but I couldn't figure out how to keep pushing the nested children. – bob.mazzo Jun 22 '15 at 17:57
  • 1
    Here I got something that seems to create a brand new array fast, let me add that to both of my answes. – fuyushimoya Jun 22 '15 at 18:25
  • I like the new idea better. I only wanted to understand where I was going wrong earlier one... – bob.mazzo Jun 22 '15 at 18:44