简体   繁体   中英

How to convert array of object into nested array of object in Javascript?

I am having an array of objects like this

[
    {
        name: "dhanush",
        goals: ["goal 1","goal 2"]
    },
    {
        name: "kumar",
        goals: ["goal 3", "goal 4"]
    },
    {
        name: "test",
        goals: ["goal 5"]
    }
]

Is that possible to convert the above array of object into the below structure like this

[
  {
    "name": "dhanush",
    "goals": "---",
    "subRows": [
      {
        "name": "",
        "goals": "goal 1"
      },
      {
        "name": "",
        "goals": "goal 2"
      }
    ]
  },
  {
    "name": "kumar",
    "goals": "---",
    "subRows": [
      {
        "name": "",
        "goals": "goal 3"
      },
      {
        "name": "",
        "goals": "goal 4"
      }
    ]
  },
  {
    "name": "Test",
    "goals": "goal 5"
  }
]

In the first data, you can see the user has multiple goals (which means the array length is more than 1), If the goal length is more than one, need to create another key and move the goal data into the above structure like this.

Why I am doing this because I got an ask to create a table that needs to support expandable rows. I used @tanstack/react-table for this row expansion. Here you can find the working demo link - https://codesandbox.io/s/tanstack-table-expansion-1t77ks?file=/src/App.js

In the demo, you can see the row can expand. For the expansion that table requires the data format like this.

I tried to do something like this,

var data = [
    {
        name: "dhanush",
        goals: ["goal 1","goal 2"]
    },
    {
        name: "kumar",
        goals: ["goal 3", "goal 4"]
    },
    {
        name: "test",
        goals: ["goal 5"]
    }
]


let result = data.map((val,i) => {
  return {
    name: val.name,
    ...(val.goals.length === 1 && {goals: val.goals[0]}),
    [val.goals.length > 1 && 'subRows']: data.map((t,j) => {
      return{
       name: "",
       goals: val.goals[j]
      }
       
    }),
  }
})

But the output I am getting like this instead of the actual structure

[
  {
    "name": "dhanush",
    "subRows": [
      {
        "name": "",
        "goals": "goal 1"
      },
      {
        "name": "",
        "goals": "goal 2"
      },
      {
        "name": ""
      }
    ]
  },
  {
    "name": "kumar",
    "subRows": [
      {
        "name": "",
        "goals": "goal 3"
      },
      {
        "name": "",
        "goals": "goal 4"
      },
      {
        "name": ""
      }
    ]
  },
  {
    "name": "test",
    "goals": "goal 5",
    "false": [
      {
        "name": "",
        "goals": "goal 5"
      },
      {
        "name": ""
      },
      {
        "name": ""
      }
    ]
  }
]

Could you please help to achieve this?

Don't try to do this all in a single object literal, it's a confusing way to create properties conditionally. Just write normal conditional statements.

 var data = [{ name: "dhanush", goals: ["goal 1", "goal 2"] }, { name: "kumar", goals: ["goal 3", "goal 4"] }, { name: "test", goals: ["goal 5"] } ] var result = data.map(({ name, goals }) => { let item = { name }; if (goals.length == 1) { item.goals = goals[0]; } else { item.goals = "---"; item.subRows = goals.map(g => ({ name: "", goals: g })); } return item; }); console.log(result);

This here

[val.goals.length > 1 && 'subRows']: data.map((tm j) => {

evaluates to false if there's 1 goal or less, and results in the string property false . Then you're mapping the whole data again inside that for some reason. Only map over the goals of the current element you're iterating over, the val.goals .

Because the different possible resulting objects are pretty differently strucured, I think this would be easier to manage if they were entirely separate - return { name, goals: goals[0] } if there's only one goal, and return a completely different object mapping over the goals otherwise.

 var data=[{name:"dhanush",goals:["goal 1","goal 2"]},{name:"kumar",goals:["goal 3","goal 4"]},{name:"test",goals:["goal 5"]}]; const result = data.map(({ name, goals }) => { return goals.length === 1 ? { name, goals: goals[0] } : { name, goals: '---', subRows: goals.map( goal => ({ name: '', goal }) ) }; }); console.log(result);

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