Home > Blockchain >  Group array of objects with a specific key value pushed first
Group array of objects with a specific key value pushed first

Time:08-25

Given the following Array of Objects:

[
    {
        "teamFK": 8650,
        "code": "yellow_cards",
        "typeId": 554,
        "value": "5",
        "side": "home"
    },
    {
        "teamFK": 8650,
        "code": "goals",
        "typeId": 554,
        "value": "1",
        "side": "home"
    },
    {
        "teamFK": 8990,
        "code": "yellow_cards",
        "typeId": 555,
        "value": "2",
        "side": "away"
    },
    {
        "teamFK": 8990,
        "code": "goals",
        "typeId": 555,
        "value": "0",
        "side": "away"
    }
]

I would like to group this data by code and get this result:

{
      "stats": [
        {
          "name": "yellow_cards",
          "stats": ["5","2"]
        },
        {
          "name": "goals",
          "stats": ["2","0"]
        }
      ]
}

What I've done is the following which works but I want to make sure that the alway the stat with "side":"home" always pushed first into the array "stats": []:

 const groupedStats = Object.entries(
    query.reduce((acc, { typeId, value, code, side }) => {
      if (!acc[code]) {
        acc[code] = [];
      }

      acc[code].push(value);

      return acc;
    }, {}),
  ).map(([name, stats]) => ({ name, stats }));

CodePudding user response:

My approach is sort it first by side using Array.sort() and then looping through the objects and adding it to stats

i created a const match to find if there is a match already so i dont have to add the name and value again basically if its not a match i'll add it to the stats array and if its a match then i'll just update the current index

const objs = [
  {
    teamFK: 8650,
    code: "yellow_cards",
    typeId: 554,
    value: "5",
    side: "home",
  },
  {
    teamFK: 8650,
    code: "goals",
    typeId: 554,
    value: "1",
    side: "away",
  },
  {
    teamFK: 8990,
    code: "yellow_cards",
    typeId: 555,
    value: "2",
    side: "away",
  },
  {
    teamFK: 8990,
    code: "goals",
    typeId: 555,
    value: "0",
    side: "home",
  },
];
let stats = [];

const transformedObj = objs
  .sort((a, b) => {
    if (a.side > b.side) {
      return -1;
    }
    if (a.side < b.side) {
      return 1;
    }
    return 0;
  })
  .forEach((obj) => {
    const match = stats.find((stat) => stat.name === obj.code);
    const statsIndex = stats.findIndex((stat) => stat.name === obj.code);
    if (!match) {
      stats = [...stats, { name: obj.code, value: [obj.value] }];
    } else {
      stats[statsIndex] = {
        name: stats[statsIndex].name,
        value: [...stats[statsIndex].value, obj.value],
      };
    }
  });

console.log(stats);

CodePudding user response:

You can sort array and use key grouping approach:

const data = [{"teamFK": 8650,"code": "yellow_cards","typeId": 554,"value": "5","side": "home"},{"teamFK": 8650,"code": "goals","typeId": 554,"value": "1","side": "home"},{"teamFK": 8990,"code": "yellow_cards","typeId": 555,"value": "2","side": "away"},{"teamFK": 8990,"code": "goals","typeId": 555,"value": "0","side": "away"}];

const groups = data
  .sort(({ side: a }, { side: b }) => b.localeCompare(a))
  .reduce((acc, { code, value }) => {
    acc[code] ??= { name: code, stats: [] };
    acc[code]['stats'].push(value);
    return acc;
  }, {});
  
const result = { stats: Object.values(groups) };

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }

  • Related