I have an object with some nested data that I need to process programmatically to achieve a certain output. It will be the easiest to explain by demonstrating with example.
Example
I conducted an experiment and measured speed of dogs and cats running. I gathered the data in the following groups object. We can see two major categories for each group, i.e., dogs and cats. Then, in each group, we have one property about the mean average speed time of the group members, as well as individuals object that holds the data about each group member.
const groups = {
  dogs: {
    groupMeanRecord: 11.7,
    individuals: {
      lassie: {
        record: 10,
        age: 2,
      },
      slinky: {
        record: 13,
        age: 4,
      },
      toto: {
        record: 11.5,
        age: 1,
      },
      marley: {
        record: 15,
        age: 1,
      },
      beethoven: {
        record: 9,
        age: 13,
      },
    },
  },
  cats: {
    groupMeanRecord: 7.75,
    individuals: {
      grumpyCat: {
        record: 6,
        age: 4,
      },
      salem: {
        record: 9,
        age: 11,
      },
      garfield: {
        record: 5,
        age: 3,
      },
      kitty: {
        record: 11,
        age: 10,
      },
    },
  },
};
I want to figure out who are the animals, in each group, whose record values are the lowest. I decided that I want the 3 lowest in each group. Hence, my desired output, given this current data, is:
const desiredOutput = {
  dogs: 'beethoven, lassie, toto',
  cats: 'garfield, grumpyCat, salem',
};
my attempt
Below is the code that I was able to come up with and it does give the desired output. However, as I'm new to JavaScript, I believe that there has to be an easier/more straightforward way to do this.
- step 1 – clean up the data to get just what I need - const cleanDataArrOfArrs = Object.entries(groups).map( ([group, groupData]) => [ group, Object.entries(groupData.individuals).map(([individual, data]) => [ individual, data.record, ]), ] ); // [ // 'dogs', // [ // ['lassie', 10], // ['slinky', 13], // ['toto', 11.5], // ['marley', 15], // ['beethoven', 9], // ], // ], // [ // 'cats', // [ // ['grumpyCat', 6], // ['salem', 9], // ['garfield', 5], // ['kitty', 11], // ], // ], // ]
- step 2 – I want to make the result of step 1 an object of objects - utilizing this helper function from here - const makeObject = (arr) => { return Object.fromEntries( arr.map(([key, val]) => Array.isArray(val) ? [key, makeObject(val)] : [key, val] ) ); };
- calling - makeObject()on- cleanDataArrOfArrs- const cleanDataObj = makeObject(cleanDataArrOfArrs) // { // dogs: { lassie: 10, slinky: 13, toto: 11.5, marley: 15, beethoven: 9 }, // cats: { grumpyCat: 6, salem: 9, garfield: 5, kitty: 11 }, // };
 
- step 3 – now I want to sort - cleanDataObj.dogsand- cleanDataObj.catsproperties from lowest to largest (respectively).- utilizing a helper function from this answer:
 - const sortObj = (o) => Object.fromEntries(Object.entries(o).sort((a, b) => a[1] - b[1]));- and finally:
 - const myOutput = Object.fromEntries( Object.entries(cleanDataObj).map(([k, v]) => [ k, Object.keys(sortObj(v)).slice(0, 3).join(', '), ]) ); // { // dogs: 'beethoven, lassie, toto', // cats: 'garfield, grumpyCat, salem', // };
My worry is that this code, although working, is neither readable nor addressing the task properly, and that there might be a much simpler way to approach this. I'd therefore be happy to learn how such a task could be otherwise done.
 
    