1

I have a Tree array of objects and I want to convert it to use it into my primeReact component

This is my input data :

[
  {
    name: "My name",
    Myid: "1",
    children: [],
    type: "type1",
    label: "Mylabel",
    function: "myfunction",
  },
  {
    name: "Name2",
    Myid: "2",
    children: [],
    type: "Type2",
    label: "Mylabel",
    function: "myfunction",
  },
  {
    name: " Another Name",
    Myid: "3",
    children: ["1", "2"],
    type: "this is my type",
    label: "My label 4",
    function: "Functionnal Component",
  },
  {
    name: "Name3",
    Myid: "5",
    children: [],
    type: "Type3",
    label: "Mylabel3",
    function: "myfunction3",
  },
  {
    name: "Name6",
    Myid: "6",
    children: ["3"],
    type: "Type6",
    label: "Mylabel6",
    function: "myfunction6",
  },
];

I want to get a Tree array like this, instead of having only id's array in children field I want to have the whole object of the children, for the above axample, each field of the array should have only 3 fields : (id,data, children) and data will have name,type,label,function.

the output should look like :

 const output = [
    {
      key: "5",
      data: {
        name: "Name3",
        type: "Type3",
        label: "Mylabel3",
        function: "myfunction3",
      },
      children: [],
    },
    {
      key: "6",
      data: {
        name: "Name6",
        type: "Type6",
        label: "Mylabel6",
        function: "myfunction6",
      },
      children: [
        {
          key: "3",
          data: {
            name: " Another Name",
            type: "this is my type",
            label: "My label 4",
            function: "Functionnal Component",
          },
          children: [
            {
              key: "1",
              data: {
                name: "My name",

                type: "type1",
                label: "Mylabel",
                function: "myfunction",
              },
              children: [],
            },
            {
              key: "2",
              data: {
                name: "Name2",
                type: "Type2",
                label: "Mylabel",
                function: "myfunction",
              },
              children: [],
            },
          ],
        },
      ],
    },
  ];

I've tried to convert my array but I don't have any idea how to convert it into a tree array

const manip = data?.map((el) => {
  return {
    key: el.Myid,
    data: {
      layer: el.layer,
      label: el.label,
      name: el.name,
      type: el.type,
    },
    children: el.children,
  };
});

console.log(manip)
Tania12
  • 323
  • 2
  • 16
  • Reopened. There is probably a duplicate we can find. But the [suggested one](https://stackoverflow.com/q/18017869) uses input elements which know their *parents*. Here the elements know their *children*, and that will take different techniques. @pilchard, traynor, jabaa -- do you disagree? – Scott Sauyet Feb 28 '23 at 13:41
  • I agree @Scott, and I'm trying to make some update to see if it will works.. – Tania12 Feb 28 '23 at 14:05
  • if it wasn't clear, some other users thought this was a duplicate of the question I mentioned, and closed this one. I disagreed and reopened it, because that one had significant differences from yours. – Scott Sauyet Feb 28 '23 at 14:07
  • Yes thank you, it's look too difficult to adapt it with my case and get the expected output, have you an idea how to achieve this ? – Tania12 Feb 28 '23 at 14:45

2 Answers2

2

You could build a new tree by looking to children and remove the children for getting the parent objects.

const
    data = [{ name: "My name", Myid: "1", children: [], type: "type1", label: "Mylabel", function: "myfunction" }, { name: "Name2", Myid: "2", children: [], type: "Type2", label: "Mylabel", function: "myfunction" }, { name: " Another Name", Myid: "3", children: ["1", "2"], type: "this is my type", label: "My label 4", function: "Functionnal Component" }, { name: "Name3", Myid: "5", children: [], type: "Type3", label: "Mylabel3", function: "myfunction3" }, { name: "Name6", Myid: "6", children: ["3"], type: "Type6", label: "Mylabel6", function: "myfunction6" }],
    getTree = data => {
        const
            t = {},
            c = new Set;

        data.forEach(({ Myid: id, children = [], ...data }) => {
            Object.assign(t[id] ??= {}, { id, data });
            t[id].children = children.map(id => {
                c.add(id);
                return t[id] ??= {};
            });
        });

        return Object.values(t).filter(o => !c.has(o.id));
    },
    tree = getTree(data);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thanks, but your output is not what I'm looking for, I want 3 property of each item (myid,data and children) – Tania12 Feb 28 '23 at 14:34
  • @Tania12; sorry, please see edit. – Nina Scholz Feb 28 '23 at 15:37
  • Worked! thank you, it's more difficult than I expect :) – Tania12 Feb 28 '23 at 15:42
  • Tree is a function or variable ? when I'm trying to paste it in my code editor I get an error, please can you clarify it ? :) thank's – Tania12 Feb 28 '23 at 15:43
  • `tree` is an array. it is that what you see in the console. – Nina Scholz Feb 28 '23 at 15:50
  • Yes, when I separate the Tree array and the data I get an error.. const data = [My array here]; const tree = getTree = data => { const t = {}, c = new Set; data.forEach(({ Myid, children = [], ...data }) => { Object.assign(t[Myid] ??= {}, { Myid, data }); t[Myid].children = children.map(id => (c.add(id), t[id] ??= {})); }); return Object.values(t).filter(o => !c.has(o.Myid)); }, tree = getTree(data); – Tania12 Feb 28 '23 at 15:53
  • I get an error :( – Tania12 Feb 28 '23 at 15:54
  • please try again. what error do you get and where? – Nina Scholz Feb 28 '23 at 15:55
  • File was processed with these loaders: * ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js * ./node_modules/babel-loader/lib/index.js You may need an additional loader to handle the result of these loaders. | ...data | }) => { > Object.assign(t[Myid] ??= {}, { | Myid, | data It's in Object.assign line – Tania12 Feb 28 '23 at 15:58
  • 1
    maybe [logical nullish assignment `??=`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment) is not working. you could replace it with `Object.assign(t[Myid] = t[Myid] || {}, { Myid, data });` – Nina Scholz Feb 28 '23 at 16:01
  • And for return (t[id] ??= {}) now, what can I replace it ? – Tania12 Feb 28 '23 at 16:03
  • 1
    with the same style `return t[id] = t[id] || {};` – Nina Scholz Feb 28 '23 at 16:06
  • This is my last question please, how can I replace Myid property with id in all tree ? – Tania12 Feb 28 '23 at 16:21
  • please see above. – Nina Scholz Feb 28 '23 at 16:25
  • 1
    by renaming properties, you need to rename **all** properties. in this case here with right property: `!c.has(o.key)`. – Nina Scholz Mar 01 '23 at 09:32
  • Hey, I got a problem when passing a long array, the error is "InternalError: too much recursion" – Tania12 Mar 27 '23 at 14:08
  • @Tania12, in my code is no recursion. maybe you have another function which calls itself. – Nina Scholz Mar 27 '23 at 14:15
  • Oh sorry, I mean when I give a big array in the getTree function, it return an empty.. Please take a look here : https://codesandbox.io/s/twilight-river-onlv1m?file=/src/App.js It should not return an empty array in this case.. – Tania12 Mar 27 '23 at 14:22
  • it looks like you have a circular reference. the key `12722` looks like the root, but some node have this id as children. so no root. what result do you expect? – Nina Scholz Mar 27 '23 at 15:01
  • Yes, the result I want is if the children array of an object contains an id of another object, then the object is the child of the parent.. It works perfectly but when I add a root Id in another node (then I expect to put THE ROOT as child of the node) – Tania12 Mar 27 '23 at 15:10
  • please ask a new question with a smaller amount of data. the amount is not really the problem here. – Nina Scholz Mar 27 '23 at 15:12
  • Yes I will do it now! – Tania12 Mar 27 '23 at 15:12
  • I just found the problem, and still looking for solution, please take a look : https://stackoverflow.com/questions/75858039/error-when-converting-array-to-tree-array-in-javascript-get-empty-array – Tania12 Mar 27 '23 at 16:16
0

Your expected output:

const data = [
  {
    name: "My name",
    Myid: "1",
    children: [],
    type: "type1",
    label: "Mylabel",
    function: "myfunction",
  },
  {
    name: "Name2",
    Myid: "2",
    children: [],
    type: "Type2",
    label: "Mylabel",
    function: "myfunction",
  },
  {
    name: " Another Name",
    Myid: "3",
    children: ["1", "2"],
    type: "this is my type",
    label: "My label 4",
    function: "Functionnal Component",
  },
  {
    name: "Name3",
    Myid: "5",
    children: [],
    type: "Type3",
    label: "Mylabel3",
    function: "myfunction3",
  },
  {
    name: "Name6",
    Myid: "6",
    children: ["3"],
    type: "Type6",
    label: "Mylabel6",
    function: "myfunction6",
  },
];

const manip = data?.map((el) => {
  return {
    key: el.Myid,
    data: {
      function: el.function,
      label: el.label,
      name: el.name,
      type: el.type,
    },
    
    children: el.children ,
  };
});


FinalRes = manip.map(obj=>{
  return {
    ...obj,
    children:obj.children.map(id=>{
      let child = data.filter(x=>x.Myid===id)[0];
      return{
        key:child.Myid,
        data:{
          name:child.name,
          type:child.type,
          label:child.label,
          function:child.function
        }
      }
    })
  }
});
console.log(FinalRes)