-1

I have some data that i need to format. The input is something like

const data = [
            ['0','some name','ok'],
            ['0.1','some name','ok'],
            ['0.1.01','some name', 'ok'],
            ['0.1.01.01','some name','ok'],
            ['0.1.01.02','some name','ok'],
            ['1','some name','ok'],

        ]

I need it to be like:

const data = [{
    code: "0"
    name: "some name"
    status: "ok"
    data:[{
        code: "0.1"
        name: "some name"
        status: "ok"
        data:[
        {
            code: "0.1.01"
            name: "some name"
            status: "ok"
            data: []
        },
        {
            code: "0.1.02"
            name: "some name"
            status: "ok"
            data:[]
        }
        ]
    },
    {
    code: "1"
    name: "some name"
    status: "ok"
    data[]
    }
    
    ]
}]

i'm going to use this data to poppulate an expandable react table, i need that kind of structure so useExpanded can handle expandable rows like this

  code       | decription  | status
__________________________________
- 0          |  some text  | ok
  - 0.1      |  some text  | ok
    + 0.1.01 |  some text  | ok
    + 0.1.02 |  some text  | ok
+ 1          |  some text  | ok

so the 'code' represents the level, each level is an array of objects

This is what i tried so far.

const formatData = () => {
        const data = [
            ['0','some name','ok'],
            ['0.1','some name','ok'],
            ['0.1.01','some name', 'ok'],
            ['0.1.01.01','some name','ok'],
            ['0.1.01.02','some name','ok'],
        ]
        const columnName = ['code','name','status']

        const result = []; 
        data.forEach((item) => {
        
            let rowInfo = {}; 
            item.forEach((item, index) => {
                rowInfo = { ...rowInfo, [columnName[index]]: item };
            });
            if (item[0].split(".").length === 1) { // If is the first level
                result.push({ ...rowInfo, subRows: [] });
            } else {
                let aux = item[0].split(".");
                aux.slice(0, -1).reduce((r, e) => { // find parent and push object to array
                    r[e].subRows.push({ ...rowInfo, subRows: [] });
                }, result);
            }
        });
        return result;
    }
    

I can get the first 3 rows, but the program breaks when trying to find sublevel array

Aventris
  • 1
  • 2

2 Answers2

0

First: run your code in a debugger, to see what it's doing. It's not what you think.

Maybe read what reduce() does.

Second, rewrite it so you're not searching through the tree for where to insert your row. All of the nodes of your tree have ids, so just make a map from those ids to the nodes. When you want to find a node, just look it up in the map.

JasonWoof
  • 4,176
  • 1
  • 19
  • 28
  • I´m going to use that info to populate an expandable react table. React table ueses subRow array to handle collapse so i really need this structure. Any ideas how can i convert the data structure?. Any ref or link would be appreciated – Aventris Jan 14 '21 at 15:02
  • I didn't say not to create the structure, I said don't search through it to find parents. make a second structure (a map) to find the parents, then insert into them – JasonWoof Jan 15 '21 at 02:39
-1

I finally solve it.

this is the solution:

var array = ["1","1.1","1.1.01","1.1.02.1",'1.2.01' ];

    result = array.reduce((r, s,rowNum) => {
        const size = s.split(".").length-1
        s.split('.').reduce((a, path,index) => 
            let object = a.find(o => o.path === path);
            if (!object && index===size) { // If object is not created and is the last child
                //create object
                a.push(object = { path, populate: [] });
            } else {
                 // If object is not created but isn't the last
                if(!object) throw `Error: ${rowNum}`; // parent object has not been created, notify user
            }
            return object.populate; // If there is an object and is not the last child, return it's own array of objects (child list)
        }, r);
        return r;
    }, []);
    
console.log(result);


I use the first reduce to get each item from array and accumulate it into an array, then i get the number of "levels" that the string will generate.

The secound reduce function iterates over levels that will be created.

If is the last level (or if it has only one level), then i create the object and return the child array that will contain the sub levels objects, so the accumulator in the next iteration is now the reference of sub level array. then i check if is the last level, if not, then return the sublevel array and if the object doesn't exists trow error

Aventris
  • 1
  • 2