0

Can anyone help converting the following list of parent-child objects:

I have below array of objects, Need to convert it into parent child order. each 'Members' attribute in object may have 1 or n objects inside it. In 'Members' array the 1st object is parent of 2nd one and 2nd is parent of third object.

So in 1st Member 'Video' is parent of 'West' and 'West' is parent of 'India' and so on..

I have tried to loop through the elements one by one but could not reach the desired outcome.

Any help with the logic or code would be really helpful.

Input :

[
  {
    "Members": [
      {
        "Name": "Videos"
      },
      {
        "Name": "West"
      },
      {
        "Name": "India"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Machinery"
      },
      {
        "Name": "South"
      },
      {
        "Name": "Australia"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Electronics"
      },
      {
        "Name": "Midwest"
      },
      {
        "Name": "Arab"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Machinery"
      },
      {
        "Name": "West"
      },
      {
        "Name": "India"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Electronics"
      },
      {
        "Name": "NorthEast"
      },
      {
        "Name": "Japan"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Videos"
      },
      {
        "Name": "South"
      },
      {
        "Name": "Australia"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Videos"
      },
      {
        "Name": "West"
      },
      {
        "Name": "Japan"
      }
    ]
  }
]

Expected Output :

[
  {
    "name": "Videos",
    "children": [
      {
        "name": "West",
        "children": [
          {
            "name": "India",
            "children": []
          },
          {
            "name": "Japan",
            "children": []
          }
        ]
      },
      {
        "name": "South",
        "children": [
          {
            "name": "Australia",
            "children": []
          }
        ]
      }
    ]
  },
  {
    "name": "Machinery",
    "children": [
      {
        "name": "South",
        "children": [
          {
            "name": "Australia",
            "children": []
          }
        ]
      },
      {
        "name": "West",
        "children": [
          {
            "name": "India",
            "children": []
          }
        ]
      }
    ]
  },
  {
    "name": "Electronics",
    "children": [
      {
        "name": "Midwest",
        "children": [
          {
            "name": "Arab",
            "children": []
          }
        ]
      },
      {
        "name": "NorthEast",
        "children": [
          {
            "name": "Japan",
            "children": []
          }
        ]
      }
    ]
  }
]

```
2
  • 2
    You have asked this before ?? ,I guess.Such questions need some efforts from your end ,that helps us to give you a better answer Commented Jun 18, 2019 at 10:02
  • 2
    @Shubh Yes, here Commented Jun 18, 2019 at 10:03

3 Answers 3

3

Man this took too long. But it works with larger datasets. Note to OP, never use this data structure. Ever. It's horrible. I lost many braincells making this solution:

var arr = [
  {Members: [{ Name: "Videos" }, { Name: "West" }, { Name: "India" }, {Name: 'Testing'}]},
  {Members: [{ Name: "Machinery" }, { Name: "South" }, { Name: "Australia" }]},
  {Members: [{ Name: "Electronics" }, { Name: "Midwest" }, { Name: "Arab" }]},
  {Members: [{ Name: "Machinery" }, { Name: "West" }, { Name: "India" }]},
  {Members: [{ Name: "Electronics" }, { Name: "NorthEast" }, { Name: "Japan" }]},
  {Members: [{ Name: "Videos" }, { Name: "South" }, { Name: "Australia" }]},
  {Members: [{ Name: "Videos" }, { Name: "West" }, { Name: "Japan" }]}
];

const addRelation = (obj, m, i) => ({...obj, parent: i === 0 ? null : m.slice(0, i).map(el => el.Name).join('.'), level: i, children: []})

const arrayToTree = (arr) => {
    arr = arr.map(({ Members: m }) => m.map((obj, i) => addRelation(obj, m, i))).reduce((acc, arr) => {
        arr.map(obj => acc.push(obj))
        return acc
    }, []).sort((a, b) => b.level - a.level)    
    
    var temp = [...arr].filter((o, index, self) =>
        index === self.findIndex((t) => (
            t.Name === o.Name && t.parent === o.parent
        ))
    )

    arr.forEach(() => {
        if (temp[0].level === 0) return
        var parentIndex = temp.findIndex(o => {
            var str = temp[0].parent
            var rest = str.substring(0, str.lastIndexOf("."));
            var last = str.substring(str.lastIndexOf(".") + 1, str.length);
            var parents = [rest, last]
            return parents[0] !== ''
              ? o.Name === parents[1] && o.parent === parents[0]
              : o.Name === temp[0].parent
        })
        const { Name, children } = temp[0]
        temp[parentIndex].children.push({Name, children})
        temp.shift()
    })
        
    return temp.map(({ Name, children }) => ({ Name, children }))
}

arr = arrayToTree(arr)
console.log(arr)

Sign up to request clarification or add additional context in comments.

14 Comments

Hello, we meet again. :D. your answer is way better than mine so dont take this in a wrong way but it does not reproduce the desired output.
@Andam I fixed that just now :)
It does work but its not the same structure as his expected outcome
@Andam Can you please point where i went wrong so i can fix it
You did not went wrong but his outcome is like this Videos > West > India, Japan but your answer is Videos > West > India, Videos > West > Japan
|
1

This might not be the best way to go about this and this only works for 3 levels.

var data = [
  {
    "Members": [
      {
        "Name": "Videos"
      },
      {
        "Name": "West"
      },
      {
        "Name": "India"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Machinery"
      },
      {
        "Name": "South"
      },
      {
        "Name": "Australia"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Electronics"
      },
      {
        "Name": "Midwest"
      },
      {
        "Name": "Arab"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Machinery"
      },
      {
        "Name": "West"
      },
      {
        "Name": "India"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Electronics"
      },
      {
        "Name": "NorthEast"
      },
      {
        "Name": "Japan"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Videos"
      },
      {
        "Name": "South"
      },
      {
        "Name": "Australia"
      }
    ]
  },
  {
    "Members": [
      {
        "Name": "Videos"
      },
      {
        "Name": "West"
      },
      {
        "Name": "Japan"
      }
    ]
  }
];


function organize(dataBefore){
  var dataAfter = [];
  
 dataAfter.push({
    name: dataBefore[0].Members[0].Name,
    children: []
  });
    
  for(var i = 1; i < dataBefore.length; i++){
    if(!doesExist(dataAfter, dataBefore[i].Members[0].Name)){
      dataAfter.push({
        name: dataBefore[i].Members[0].Name,
        children: []
      });
    }
  }

  dataAfter[0].children.push({
    name: dataBefore[0].Members[1].Name,
    children: []
  });

  for(var i = 1; i < dataBefore.length; i++){
      for(var j = 0; j < dataAfter.length; j++){
          if(dataAfter[j].name == dataBefore[i].Members[0].Name){
            if(!doesExist(dataAfter[j].children, dataBefore[i].Members[1].Name)){
                dataAfter[j].children.push({
                    name: dataBefore[i].Members[1].Name,
                    children: []
                });
            }
          }
      }
  }

  dataAfter[0].children[0].children.push({
    name: dataBefore[0].Members[2].Name,
    children: []
  });

  for(var i = 1; i < dataBefore.length; i++){
      for(var j = 0; j < dataAfter.length; j++){
        if(dataAfter[j].name == dataBefore[i].Members[0].Name){
            for(var k = 0; k < dataAfter[j].children.length; k++){
                if(dataAfter[j].children[k].name == dataBefore[i].Members[1].Name){
                    if(!doesExist(dataAfter[j].children[k].children, dataBefore[i].Members[2].Name)){
                        dataAfter[j].children[k].children.push({
                            name: dataBefore[i].Members[2].Name,
                            children: []
                        });
                    }
                }
            }
        }
      }
  }

  return dataAfter;
}

function doesExist(checkThisData, searchValue){
    for(var i = 0; i < checkThisData.length; i++){
        if(searchValue == checkThisData[i].name){
            return true;
        }
    }
  
    return false;
}

console.log(organize(data));

9 Comments

This is very over complicated :p
@Adnam - Thanks for the code , It works very well for the level 3 . By any chance can you help in in any way for not restricting it to only level 3. Thanks for your efforts
yes I believe I can. I will try and get back to you
I can't come up with a solution lol. The data structure is horrendous :p +1, Nicely done. I'll continue trying though ;)
@Kobe Yes, I agree. The challenge is the fun part here. About the result I think you have an extra node in the beginning. you have two videos > west nodes in the answer. as far as I figured out.
|
-1

I would advise to use map + reduce combination:

const data = [{
    "Members": [{
        "Name": "Videos"
      },
      {
        "Name": "West"
      },
      {
        "Name": "India"
      }
    ]
  },
  {
    "Members": [{
        "Name": "Machinery"
      },
      {
        "Name": "South"
      },
      {
        "Name": "Australia"
      }
    ]
  },
  {
    "Members": [{
        "Name": "Electronics"
      },
      {
        "Name": "Midwest"
      },
      {
        "Name": "Arab"
      }
    ]
  },
  {
    "Members": [{
        "Name": "Machinery"
      },
      {
        "Name": "West"
      },
      {
        "Name": "India"
      }
    ]
  },
  {
    "Members": [{
        "Name": "Electronics"
      },
      {
        "Name": "NorthEast"
      },
      {
        "Name": "Japan"
      }
    ]
  },
  {
    "Members": [{
        "Name": "Videos"
      },
      {
        "Name": "South"
      },
      {
        "Name": "Australia"
      }
    ]
  },
  {
    "Members": [{
        "Name": "Videos"
      },
      {
        "Name": "West"
      },
      {
        "Name": "Japan"
      }
    ]
  }
];

const ar = data.map((el, i) => {
  let a = el['Members'].reduce((acc, member, index) => {
    if (index === 0) {
      acc[index] = {
        name: member.Name,
        children: []
      };
    } else {
      debugger;
      if (acc[0].children.length === 0) {
        acc[0].children.push({
          name: member.Name,
          children: []
        });
      } else {
        acc[0].children[0].children.push({
          name: member.Name,
          children: []
        });
      }
    }

    return acc;
  }, []);

  return a;
});

console.log(ar);

1 Comment

your answer like kobe answer does not reproduce the same result as his result. his outcome is like this Videos > West > India, Japan but your answer is Videos > West > India, Videos > West > Japan

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.