Home > Net >  Group objects from an array of objects based on two or more keys and from an array of dynamically co
Group objects from an array of objects based on two or more keys and from an array of dynamically co

Time:07-17

I need to group objects based on two or more filters on known keys from the values of the dataset.

I believe filtering is the best approach but all of my attempts have failed.

var uniqueKeys = ['course','gradDate'];

var dataSet = [
  {
    lastName:'Jones',
    course:'Standards',
    gradDate:'12/12/2022'
  },
{    
    lastName:'Smith',
    course:'Standards',
    gradDate:'12/12/2022'
  },
{
    lastName:'Martinez',
    course:'Maths',
    gradDate:'12/12/2022'
  },
{
    lastName:'Santiago',
    course:'Photography',
    gradDate:'12/11/2022'
  },
{
    lastName:'Alexi',
    course:'Photography',
    gradDate:'12/11/2022'
  }
]

function returnUniqueValues(array,key){
    return UniqueValue = [...new Set(array.map(item => item[key]))]
}

var uniqueCourses = returnUniqueValues(dataSet,'course') 
//result for this dataset === ["Standards","Maths","Photography"];
var uniqueGradDates = returnUniqueValues(dataSet,'gradDate') 
//Result for this dataset === ["12/12/2022","12/11/2022"];

From here I have two arrays of unique values that I need to group objects from the source dataset (dataSet)

I apologize if I am not describing this correctly, hopefully the example of the expected output will clear it up.

For all steps, if nothing matches the double filter, nothing should return. Example step through at least with how I have been approaching this problem, follows:

The first step would filter dataSet for all objects that have a course === "Standards" and a gradDate === "12/12/2022". Here I would would get two objects back. I would then pass that to a new array for reference later.

Second step would filter the source dataset, dataSet for any object that has course === "Standards" and gradDate === "12/11/2022".

Third step would filter dataSet for all objects where the course === "Maths" and gradDate === "12/12/2022"

Example output for this dataset would by

var finalData = [
    [{
            lastName: 'Jones',
            course: 'Standards',
            gradDate: '12/12/2022'
        },
        {
            lastName: 'Smith',
            course: 'Standards',
            gradDate: '12/12/2022'
        },
    ],
    [{
        lastName: 'Martinez',
        course: 'Maths',
        gradDate: '12/12/2022'
    }],
    [{
            lastName: 'Santiago',
            course: 'Photography',
            gradDate: '12/11/2022'
        },
        {
            lastName: 'Alexi',
            course: 'Photography',
            gradDate: '12/11/2022'
        }
    ]
]

End goal is to then loop through each group (in this case of anybody with the same course and gradDate pairs) and populate a report with their information like lastname. In this example there are 3 unique combinations of course and gradDate that actually exist. Scaling, I full expect thousands of different courses with up to 4 different dates possible.

CodePudding user response:

You can simply use a 'group-by' with a compound key of the specified properties.

Here calling map() and join() on your uniqueKeys array for each iterated object to generate the compound key, then retrieving or initializing the property using logical nullish assignment (??=) before pushing the object to it. The result is the Object.values() of the grouped object.

const dataSet = [{ lastName: 'Jones', course: 'Standards', gradDate: '12/12/2022' }, { lastName: 'Smith', course: 'Standards', gradDate: '12/12/2022' }, { lastName: 'Martinez', course: 'Maths', gradDate: '12/12/2022' }, { lastName: 'Santiago', course: 'Photography', gradDate: '12/11/2022' }, { lastName: 'Alexi', course: 'Photography', gradDate: '12/11/2022' }];

const uniqueKeys = ['course', 'gradDate'];
const grouped = {};

for (const o of dataSet) {
  const key = uniqueKeys.map(k => o[k]).join('_');
  (grouped[key] ??= []).push(o);
}

const result = Object.values(grouped)

console.log(result);

  • Related