1

I am a beginner in javascript object and tree creation, so please bear with me. I have an array of objects like this

[
    {
        "l1": 1,
        "l2": 2,
        "l3": 3,
        "l4": 4,
        "l5": 5,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 3,
        "l4": 4,
        "l5": 6,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 7,
        "l4": 8,
        "l5": 9,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 7,
        "l4": 8,
        "l5": 10,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 3,
        "l4": 11,
        "l5": 12,
        "l6": null
    },
    {
        "l1": 1,
        "l2": 2,
        "l3": 3,
        "l4": 11,
        "l5": 13,
        "l6": null
    }
]

I have stored this data in json file, and I want to create a tree-structure-like object using this array of objects. Something like this.

{
  "1": [
    {
      "2": [
        {
          "3": [
            {
              "4": [
                {
                  "5": [
                    null
                  ]
                },
                {
                  "6": [
                    null
                  ]
                }
              ]
            },
            {
              "11": [
                {
                  "12": [
                    null
                  ]
                },
                {
                  "13": [
                    null
                  ]
                }
              ]
            }
          ]
        },
        {
          "7": [
            {
              "8": [
                {
                  "9": [
                    null
                  ]
                },
                {
                  "10": [
                    null
                  ]
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

I am trying to do this on my own but I'm failing right in the beginning itself.

This is my attempt

var fs = require('fs');
var file = 'levels.json';
var content = fs.readFileSync(file, { encoding: 'binary' });
var obj = {}
JSON.parse(content).forEach((curr, i, arr)=>{
    if(curr.l1){
        obj[curr.l1] = []
    }
    if(curr.l2){
        var l2obj = {}
        l2obj[curr.l2] = []
        obj[curr.l1].push(l2obj)
        // obj[curr.l1].push({curr.l2:[]})
    }
})

fs.writeFileSync('theObject.json', JSON.stringify(obj), 'utf8');

The problem I found out is that the line l2obj[curr.l2] = [] is overwriting the previous array and I'm not able to nest them properly.SAme problem exists with the line obj[curr.l1] = []. I tried the commented line as well but it throwing syntax error. I feel it is pretty basic but also very confusing, how do I create objects from dynamic values and push them to an array without overwriting the previous one. Any suggestions, hints.
Second line of question, Is this the best way to represent data like this? I wanted to use a tree structure because it seemed like an accurate and shortest form of data structure.The json data has almost 20k objects with level information. Suggestions are highly appreciated.

anoop chandran
  • 1,460
  • 5
  • 23
  • 42
  • 3
    Can you please explain the intended logic behind the transformation? – Máté Safranka Apr 24 '18 at 09:45
  • I have a big list(almost 20k rows) of category names and their sub category names nested upto 6 levels. I assumed tree structure would be the optimum(shortest) data structure to find the immediate siblings and parent. – anoop chandran Apr 24 '18 at 09:52
  • https://stackoverflow.com/questions/28695348/pushing-item-into-a-multi-dimensional-tree-like-structure-in-javascript - try this – codebot Apr 24 '18 at 09:55

2 Answers2

1

You could first build a bit different nested structure without arrays and then use other recursive function to iterate through that data and change it do desired output.

const data =[{"l1":1,"l2":2,"l3":3,"l4":4,"l5":5,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":4,"l5":6,"l6":null},{"l1":1,"l2":2,"l3":7,"l4":8,"l5":9,"l6":null},{"l1":1,"l2":2,"l3":7,"l4":8,"l5":10,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":11,"l5":12,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":11,"l5":13,"l6":null}]
const result = {}

data.forEach(o => {
  Object.keys(o).reduce((r, e, i, arr) => {
    const key = o[e];
    if (o[e] == null) return r;
    if (o[arr[i + 1]] == null) r[key] = null
    else if (!r[key]) r[key] = {}
    return r[key]
  }, result)
})

function build(input) {
  for (let key in input) {
    if (input[key] && Object.keys(input[key]).length) build(input[key]);
    input[key] = [input[key]]
  }
}

build(result)

console.log(result)

Update: You can also get nested structure with just objects like this.

const data =[{"l1":1,"l2":2,"l3":3,"l4":4,"l5":5,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":4,"l5":6,"l6":null},{"l1":1,"l2":2,"l3":7,"l4":8,"l5":9,"l6":null},{"l1":1,"l2":2,"l3":7,"l4":8,"l5":10,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":11,"l5":12,"l6":null},{"l1":1,"l2":2,"l3":3,"l4":11,"l5":13,"l6":null}]
const result = {}

data.forEach(o => {
  Object.keys(o).reduce((r, e) => {
    if (o[e] == null) return r;
    return r[o[e]] = (r[o[e]] || {})
  }, result)
})

console.log(result)
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
0

I figured this out, I had to change the format of result, instead of array I used object format itself. I realized the array data structure was defeating my purpose. so the result I actually wanted was

{
  "1": {
    "2": {
      "3": {
        "4": {
          "5": {},
          "6": {}
        },
        "11": {
          "12": {},
          "13": {}
        }
      },
      "7": {
        "8": {
          "9": {},
          "10": {}
        }
      }
    }
  }
}

Solution looks little wierd but very simple to understand, I'm running 6 passes to create the nesting objects.

var data = JSON.parse(content)
data.forEach((curr, i, arr)=>{
    if(curr.l1){
        obj[curr.l1] = {}
    }
})
data.forEach((curr, i, arr)=>{
    if(curr.l2 ){            
        obj[curr.l1][curr.l2] = {}
    }
})
data.forEach((curr, i, arr)=>{
    if(curr.l3 ){            
        obj[curr.l1][curr.l2][curr.l3] = {}
    }
})
data.forEach((curr, i, arr)=>{
    if(curr.l4 ){            
        obj[curr.l1][curr.l2][curr.l3][curr.l4] = {}
    }
})
data.forEach((curr, i, arr)=>{
    if(curr.l5 ){            
        obj[curr.l1][curr.l2][curr.l3][curr.l4][curr.l5] = {}
    }
})
data.forEach((curr, i, arr)=>{
    if(curr.l6 ){            
        obj[curr.l1][curr.l2][curr.l3][curr.l4][curr.l5][curr.l6] = {}
    }
})
anoop chandran
  • 1,460
  • 5
  • 23
  • 42