Home > front end >  How to create a new array using the values of an array of objects within objects?
How to create a new array using the values of an array of objects within objects?

Time:06-22

(This is a similar but more complex scenario to a previous question)

I have an array originalArrayData like so:

originalArrayData = [{
    "16": {
        "id": 22,
        "grid_row_id": 5,
        "grid_col_id": 16,
        "data": "10",
        "created_at": "rertte",
        "error_mgs": null
    },
    "header": "BUTTERFLY HEADER",
    "id": 5
},
{
    "17": {
        "id": 31,
        "grid_row_id": 9,
        "grid_col_id": 16,
        "data": "14",
        "created_at": "rtyhtyjtdyj",
        "error_mgs": null
    },
    "header": "BUTTERFLY HEADER",
    "id": 6
},
{
    "18": {
        "id": 35,
        "grid_row_id": 9,
        "grid_col_id": 12,
        "data": "55",
        "created_at": "thrtuhrs",
        "error_mgs": null
    },
    "header": "PARROT HEADER",
    "id": 6
},
{
    "19": {
        "id": 36,
        "grid_row_id": 9,
        "grid_col_id": 12,
        "data": "31",
        "created_at": "rtyhtyjtdyj",
        "error_mgs": null
    },
    "header": "PARROT HEADER",
    "id": 7
},
{
    "20": {
        "id": 36,
        "grid_row_id": 9,
        "grid_col_id": 14,
        "data": "31",
        "created_at": "rtyhtyjtdyj",
        "error_mgs": null
    },
    "header": "OTHER HEADER",
    "id": 7
}...........

Let's say I have an array of ids (these numbers could be random and there isn't always 2. There could be 1, 3, etc. array items)

arrayOfIds: [16 , 12]

If the value of grid_col_id is present anywhere in the arrayOfIds, then for each object with the same grid_col_id, how can I create a new array with new keys made using the "header" value, and the value of those keys being the sum of the "data" value of all items with the same grid_col_id.

TARGET / EXPECTED OUTPUT:

[{ "butterflyheader": 24, "parrotheader": 86, "category": "None"}]

EXPLANATION: If you look at each item in originalArrayData (for this example there are 4, but there can be many), the first 2 items have the same grid_col_id and the same header. For those two, the "data" = "10" and "14", which when added results in 24. Hence, you have "butterflyheader": 24.

The same logic can be applied to parrotheader. All new keys are the lowercase and no space version of the original "header" of each object.

The item with header "OTHER HEADER" isn't included because its grid_col_id does not exist in arrayOfIds. "category": "None" is always there and can be 'hard coded' into the new array.

To solve the issue, I have the following code:

        // creates an array of all of the innermost objects in the original array
        let tableDataFiltered = originalArrayData.map(item => 
            Object.values(item).filter(item => typeof item === "object")
        ).flat()

        // Retrieve all items with the relevant grid_col_id
        tableDataFiltered.filter(item => arrayOfIds.includes(item.grid_col_id))

        // Headers to use as keys
        let headersAsKeys = tableDataFiltered.forEach(item => {
            item.header.toLowerCase().split(' ').join(''))
        })

        Object.values(tableDataFiltered.reduce((acc, curr) => {
            acc[curr.category] = 'None';
            headersAsKeys.forEach(key => {
                acc[curr.category][key]  = curr[key];
            })
            return acc;
        }, {}));

However, it results in headersAsKeys.forEach is not a function.

How can I achieve the target array? =>

[{ "butterflyheader": 24, "parrotheader": 86, "category": "None"}]

CodePudding user response:

You only need a single loop for this. When looking at an object you're iterating over, check if the grid_col_id is the one you're looking for. If it is, add the data value to the output object (which starts with { category: 'none' }, summing with the previous value there if there is one. At the end, surround the resulting object in an array.

const originalArrayData=[{16:{id:22,grid_row_id:5,grid_col_id:16,data:"10",created_at:"rertte",error_mgs:null},header:"BUTTERFLY HEADER",id:5},{17:{id:31,grid_row_id:9,grid_col_id:16,data:"14",created_at:"rtyhtyjtdyj",error_mgs:null},header:"BUTTERFLY HEADER",id:6},{18:{id:35,grid_row_id:9,grid_col_id:12,data:"55",created_at:"thrtuhrs",error_mgs:null},header:"PARROT HEADER",id:6},{19:{id:36,grid_row_id:9,grid_col_id:12,data:"31",created_at:"rtyhtyjtdyj",error_mgs:null},header:"PARROT HEADER",id:7},{20:{id:36,grid_row_id:9,grid_col_id:14,data:"31",created_at:"rtyhtyjtdyj",error_mgs:null},header:"OTHER HEADER",id:7}];
const arrayOfIds = [16, 12];

const outputObj = { category: 'none' };
for (const { header, id, ...rest } of originalArrayData) {
  const { grid_col_id, data } = Object.values(rest)[0];
  if (arrayOfIds.includes(Number(grid_col_id))) {
    outputObj[header] = (outputObj[header] || 0)   Number(data);
  }
}
console.log([outputObj]);

CodePudding user response:

You can use Array#reduce with an object to store the data for each of the headers.

const arr=[{"16":{id:22,grid_row_id:5,grid_col_id:16,data:"10",created_at:"rertte",error_mgs:null},header:"BUTTERFLY HEADER",id:5},{"17":{id:31,grid_row_id:9,grid_col_id:16,data:"14",created_at:"rtyhtyjtdyj",error_mgs:null},header:"BUTTERFLY HEADER",id:6},{"18":{id:35,grid_row_id:9,grid_col_id:12,data:"55",created_at:"thrtuhrs",error_mgs:null},header:"PARROT HEADER",id:6},{"19":{id:36,grid_row_id:9,grid_col_id:12,data:"31",created_at:"rtyhtyjtdyj",error_mgs:null},header:"PARROT HEADER",id:7},{"20":{id:36,grid_row_id:9,grid_col_id:14,data:"31",created_at:"rtyhtyjtdyj",error_mgs:null},header:"OTHER HEADER",id:7}];
const ids = [16 , 12];
let res = [arr.reduce((acc, {header,id,...rest})=>{
  let [{grid_col_id, data}] = Object.values(rest);
  header = header.toLowerCase().replaceAll(' ', '');
  if(ids.includes(grid_col_id)) 
    acc[header] = (acc[header] || 0)    data;
  return acc;
}, {category: "None"})];
console.log(res);

  • Related