JumpIntoTheWater
JumpIntoTheWater

Reputation: 1336

get grouped by array

I have a JSON file and I would like this JSON to be grouped by according to three fields in it.

The JSON looks as follow(with more items of course):

{
  "Racename": "10KM",
  "Category": 34,
  "Gender": "Male",
  "Work": "Google",
  "FullName": "Dave Happner",
  "Rank": 1,
  "Ponit": 1,
  "Numparticipant": 0,
  "rankparticipant": 0,
  "precentagePart": "0",
  "NumRaces": 1,
  "RaceTime": "2018-10-18T00:34:20",
  "rankCat": 1,
  "PointCat": 1,
  "RaceDate": "2018-10-05"
}

The requested result (using underscore or lodash) is:

 [
   {
     "Racename" : "10KM",
     "Category": "34",
     "Gender": "Male",
     runner : [
     {
      "Work": "Google",
      "FullName": "Dave Happner",
      "Rank": 1,
      "Ponit": 1,
      "Numparticipant": 0,
      "rankparticipant": 0,
      "precentagePart": "0",
      "NumRaces": 1,
      "RaceTime": "2018-10-18T00:34:20",
      "rankCat": 1,
      "PointCat": 1,
      "RaceDate": "2018-10-05"
     }]

Upvotes: 1

Views: 72

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370949

You can reduce into an object indexed by a string, made up of the Racename, Category, and Gender, joined by a character that won't be present in the values, such as _. For example, your input in the question would result in an object with a key of 10KM_34_Male. On every iteration, check to see if the constructed key exists - if it doesn't, create the object, with an empty runner array. Then, push to the runner array.

After you've finished with the reduce, you can get the object's values to get your desired array output:

const input = [{
  "Racename": "10KM",
  "Category": 34,
  "Gender": "Male",
  "Work": "Google",
  "FullName": "Dave Happner",
  "Rank": 1,
  "Ponit": 1,
  "Numparticipant": 0,
  "rankparticipant": 0,
  "precentagePart": "0",
  "NumRaces": 1,
  "RaceTime": "2018-10-18T00:34:20",
  "rankCat": 1,
  "PointCat": 1,
  "RaceDate": "2018-10-05"
}];

const outputObj = input.reduce((a, { Racename, Category, Gender, ...rest }) => {
  const key = [Racename, Category, Gender].join('_');
  if (!a[key]) {
    a[key] = { Racename, Category, Gender, runner: [] };
  }
  a[key].runner.push(rest);
  return a;
}, {});
const output = Object.values(outputObj);
console.log(output);

Or, using a larger input:

const input = [{
  "Racename": "10KM",
  "Category": 34,
  "Gender": "Male",
  "Work": "Google",
  "FullName": "Dave Happner",
  "Rank": 1,
  "Ponit": 1,
  "Numparticipant": 0,
  "rankparticipant": 0,
  "precentagePart": "0",
  "NumRaces": 1,
  "RaceTime": "2018-10-18T00:34:20",
  "rankCat": 1,
  "PointCat": 1,
  "RaceDate": "2018-10-05"
},{
  "Racename": "10KM",
  "Category": 34,
  "Gender": "Male",
  "Work": "Amazon",
  "FullName": "Bob Joe",
  "Rank": 12,
  "Ponit": 2,
  "Numparticipant": 0,
  "rankparticipant": 0,
  "precentagePart": "0",
  "NumRaces": 1,
  "RaceTime": "2018-10-18T00:34:20",
  "rankCat": 1,
  "PointCat": 1,
  "RaceDate": "2018-10-05"
},{
  "Racename": "20KM",
  "Category": 40,
  "Gender": "Male",
  "Work": "Google",
  "FullName": "Dave Happner",
  "Rank": 1,
  "Ponit": 1,
  "Numparticipant": 0,
  "rankparticipant": 0,
  "precentagePart": "0",
  "NumRaces": 1,
  "RaceTime": "2018-10-18T00:34:20",
  "rankCat": 1,
  "PointCat": 1,
  "RaceDate": "2018-10-05"
}
];

const outputObj = input.reduce((a, { Racename, Category, Gender, ...rest }) => {
  const key = [Racename, Category, Gender].join('_');
  if (!a[key]) {
    a[key] = { Racename, Category, Gender, runner: [] };
  }
  a[key].runner.push(rest);
  return a;
}, {});
const output = Object.values(outputObj);
console.log(output);

Upvotes: 1

Related Questions