简体   繁体   中英

How to create a nested object from data using JavaScript?

Before

This is an object with multiple rows:

  {
  "functions": [
    {
      "package_id": "2",
      "module_id": "2",
      "data_id": "2"
    },
    {
      "package_id": "1",
      "module_id": "1",
      "data_id": "2"
    },
    {
      "package_id": "2",
      "module_id": "3",
      "data_id": "3"
    }
  ]
}

Desired result

I want this to return into a "nested" Object like below, without duplicates:

{
  "packages": [
    {
      "package_id": "2",
      "modules": [
        {
          "module_id": "2",
          "data": [
            {
              "data_id": "2"
            }
          ]
        },
        {
          "module_id": "3",
          "data": [
            {
              "data_id": "3"
            }
          ]
        }
      ]
    },{
      "package_id": "1",
      "modules": [
        {
          "module_id": "1",
          "data": [
            {
              "data_id": "2"
            }
          ]
        }
      ]
    }
  ]
}

I've already tried loops inside loops, with constructing multiple arrays and objects. Which causes duplicates or overriding objects into single ones. Is there a more generic way to generate this with JavaScript? (It's for an Angular (6) project.

Example 1

getFunctionPackage() {

        var fList = this.functionList;

        var dArr = [];
        var dObj = {};

        var pArr = [];
        var pObj = {};

        var mArr = [];
        var mObj = {};

        for (var key in fList) {

            pObj['package_id'] = fList[key]['package_id'];
            mObj['module_id'] = fList[key]['module_id'];
            dObj['data_id'] = fList[key]['data_id'];

            for (var i = 0; i < pArr.length; i++) {
                if (pArr[i].package_id != pObj['package_id']) {
                    pArr.push(pObj);
                }
                for (var x = 0; x < mArr.length; x++) {
                    if (pArr[i]['modules'][x].module_id != mObj['module_id']) {
                        mArr.push(mObj);
                    }
                    for (var y = 0; y < dArr.length; y++) {
                        if (pArr[i]['modules'][x]['datas'][y].data_id != dObj['data_id']) {
                            dArr.push(dObj);
                        }
                    }
                }
            }

            if (dArr.length == 0) {
                dArr.push(dObj);
            }
            mObj['datas'] = dArr;

            if (mArr.length == 0) {
                mArr.push(mObj);
            }
            pObj['modules'] = mArr;

            if (pArr.length == 0) {
                pArr.push(pObj);
            }
            dObj = {};
            mObj = {};
            pObj = {};
        }
    }

Example 2: Results in skipping cause of the booleans

 var fList = this.functionList;

var dArr = [];
var dObj = {};

var pArr = [];
var pObj = {};

var mArr = [];
var mObj = {};

var rObj = {};

for (var key in fList) {

    pObj['package_id'] = fList[key]['package_id'];
    mObj['module_id'] = fList[key]['module_id'];
    dObj['data_id'] = fList[key]['data_id'];

    var pfound = false;
    var mfound = false;
    var dfound = false;
    
    for (var i = 0; i < pArr.length; i++) {
        if (pArr[i].package_id == pObj['package_id']) {
            for (var x = 0; x < mArr.length; x++) {
                if (pArr[i]['modules'][x].module_id == mObj['module_id']) {
                    for (var y = 0; y < dArr.length; y++) {
                        if (pArr[i]['modules'][x]['datas'][y].data_id == dObj['data_id']) {
                            dfound = true;
                            break;
                        }
                    }
                    mfound = true;
                    break;
                }
            }
            pfound = true;
            break;
        }
    }
    if (!dfound) {
        dArr.push(dObj);
        mObj['datas'] = dArr;
        dObj = {};
    }

    if (!mfound) {
        mArr.push(mObj);
        pObj['modules'] = mArr;
        mObj = {};
    }

    if (!pfound) {
        pArr.push(pObj);
        pObj = {};
    }

    dArr = [];
    mArr = [];
}

rObj['packages'] = pArr;
console.log(rObj);

Here's a more generic approach using Array#reduce() to create a grouped object based on the package id as keys. You can use any loop to build this same object ... for() or forEach() for example.

Then use Object.values() to get the final array from that grouped object

Using methods like Array#find() simplifies traversing to see if a module exists already or not within each package

 const grouped = data.functions.reduce((a, c )=>{ // if group object doesn't exist - create it or use existing one a[c.package_id] = a[c.package_id] || {package_id : c.package_id, modules: [] } // store reference to the group modules array const mods = a[c.package_id].modules // look within that group modules array to see if module object exists let module = mods.find(mod => mod.module_id === c.module_id) if(!module){ // or create new module object module = {module_id: c.module_id, data:[]} // and push it into modules array mods.push(module); } // push new data object to module data array module.data.push({data_id: c.data_id}) return a }, {}) // create final results object const res = { packages : Object.values(grouped) } console.log(res)
 .as-console-wrapper {max-height: 100%!important;}
 <script> const data = { "functions": [{ "package_id": "2", "module_id": "2", "data_id": "2" }, { "package_id": "1", "module_id": "1", "data_id": "2" }, { "package_id": "2", "module_id": "3", "data_id": "3" } ] } </script>

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