Search code examples
javascriptangularjsjsonlodashangular-filters

Group json object either using lodash or for loop


so i have this array :

[
  {
    corequisite: "",
    curriculumYr: "2017-2018",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "GMRC 101||Math 101"
    semester: "1st Term",
    year: "1st Year",
    subjectCode : "ENG 101",
    units : "9"
  },
  {
    corequisite: "SOFTENG1||SOFTENG2",
    curriculumYr: "2017-2018",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "COMP 1"
    semester: "1st Term",
    year: "1st Year",
    subjectCode : "THESIS101",
    units : "9"
  },
  {
    corequisite: "",
    curriculumYr: "2017-2018",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "Sample1||Sample2"
    semester: "2nd Term",
    year: "1st Year",
    subjectCode : "SampleSubj101",
    units : "9"
  },
  {
    corequisite: "",
    curriculumYr: "2017-2018",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "SSSS4||S6"
    semester: "1st Term",
    year: "2nd Year",
    subjectCode : "S1",
    units : "9"
  },
  {
    corequisite: "SSS2||SSS4",
    curriculumYr: "2017-2018",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "COMP 1"
    semester: "2nd Term",
    year: "2nd Year",
    subjectCode : "S2",
    units : "9"
  },
  {
    corequisite: "",
    curriculumYr: "2017-2018",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "SS1||SS2"
    semester: "1st Term",
    year: "2nd Year",
    subjectCode : "S3",
    units : "9"
  }
],
[
  {
    corequisite: "",
    curriculumYr: "2018-2019",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "GMRC 101||Math 101"
    semester: "1st Term",
    year: "1st Year",
    subjectCode : "ENG 101",
    units : "9"
  },
  {
    corequisite: "SOFTENG1||SOFTENG2",
    curriculumYr: "2018-2019",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "COMP 1"
    semester: "1st Term",
    year: "1st Year",
    subjectCode : "THESIS101",
    units : "9"
  },
  {
    corequisite: "",
    curriculumYr: "2018-2019",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "Sample1||Sample2"
    semester: "2nd Term",
    year: "1st Year",
    subjectCode : "SampleSubj101",
    units : "9"
  },
  {
    corequisite: "",
    curriculumYr: "2018-2019",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "SSSS4||S6"
    semester: "1st Term",
    year: "2nd Year",
    subjectCode : "S1",
    units : "9"
  },
  {
    corequisite: "SSS2||SSS4",
    curriculumYr: "2018-2019",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "COMP 1"
    semester: "2nd Term",
    year: "2nd Year",
    subjectCode : "S2",
    units : "9"
  },
  {
    corequisite: "",
    curriculumYr: "2018-2019",
    programCode: "ET"
    majorCode: "AET",
    prerequisites: "SS1||SS2"
    semester: "1st Term",
    year: "2nd Year",
    subjectCode : "S3",
    units : "9"
  }
]

i wanted to group this by programCode,curriculumYear and majorCode and then with the grouped output group it again by Semester and Year

i also wanted to make an array of the prerequisite and corequisite by splitting the subjects with delimiter ||

here is an example output / desired output:

  [
      curriculumYr: '2017-2018',
      programCode: 'ET',
      majorCode: 'ATO'
      ,{ Sem: [
              subjects : [{
                             Corequisites: ['Subj1','Subj2'],
                             Prequisites: [],
                             subjectCode: "Sample1"
                           },
                           {
                             Corequisites: ['Subj1','Subj2'],
                             Prequisites: [],
                             subjectCode: "Sample1"                       
                           }],
              term: "1st Term"
            }],
            [{ 
               subjects: [2nd term subjects here], 
               term: "2nd Term" 
            }]
       Year: "1st Year"
   }],
    [
      curriculumYr: '2018-2019',
      programCode: 'ET',
      majorCode: 'ATO'
      ,{ Sem: [
              subjects : [{
                             Corequisites: ['Subj1','Subj2'],
                             Prequisites: [],
                             subjectCode: "Sample1"
                           },
                           {
                             Corequisites: ['Subj1','Subj2'],
                             Prequisites: [],
                             subjectCode: "Sample1"                       
                           }],
              term: "1st Term"
            }],
            [{ 
               subjects: [2nd term subjects here], 
               term: "2nd Term" 
            }]
       Year: "1st Year"
   }]

Same as for the 2nd Year's 1st and 2nd Terms format

I tried using angular-filter and lodash but i get different results. Way to different :D

Thank you so much for the help!


Solution

  • With plain javascript, you could use a function for converting, renaming and grouping the data into a new nested array.

    The function makes use of a hash table for each nested level and iterates the given keys as grouping property and add on every stage a new array for the result set.

    function getGrouped(array, keys, callback, children) {
        var result = [],
            hash = { _: result };
    
        callback = callback || function (o) { return o; };
        children = children || [];
        array.forEach(function (a) {
            keys.reduce(function (r, k, i) {
                var temp = {},
                    key = a[k],
                    target = k;
    
                if (Array.isArray(k)) {
                    key = k.map(function (b) { return a[b]; }).join('|');
                } else if (typeof k === 'object') {
                    key = a[Object.keys(k)[0]];
                    target = k[Object.keys(k)[0]];
                }
    
                if (!r[key]) {
                    r[key] = { _: [] };
                    if (Array.isArray(k)) {
                        k.forEach(function (b) { temp[b] = a[b]; });
                    } else {
                        temp[target] = key;
                    }
                    temp[children[i] || 'children'] = r[key]._;
                    r._.push(temp);
                }
                return r[key];
            }, hash)._.push(callback(a));
        });
        return result;
    }
    
    var data = [{ corequisite: "", curriculumYr: "2017-2018", programCode: "ET", majorCode: "AET", prerequisites: "GMRC 101||Math 101", semester: "1st Term", year: "1st Year", subjectCode: "ENG 101", units: "9" }, { corequisite: "SOFTENG1||SOFTENG2", curriculumYr: "2017-2018", programCode: "ET", majorCode: "AET", prerequisites: "COMP 1", semester: "1st Term", year: "1st Year", subjectCode: "THESIS101", units: "9" }, { corequisite: "", curriculumYr: "2017-2019", programCode: "ET", majorCode: "AET", prerequisites: "Sample1||Sample2", semester: "2nd Term", year: "1st Year", subjectCode: "SampleSubj101", units: "9" }, { corequisite: "", curriculumYr: "2017-2019", programCode: "ET", majorCode: "AET", prerequisites: "SSSS4||S6", semester: "1st Term", year: "2nd Year", subjectCode: "S1", units: "9" }, { corequisite: "SSS2||SSS4", curriculumYr: "2017-2018", programCode: "ET", majorCode: "AET", prerequisites: "COMP 1", semester: "2nd Term", year: "2nd Year", subjectCode: "S2", units: "9" }, { corequisite: "", curriculumYr: "2017-2018", programCode: "ET", majorCode: "AET", prerequisites: "SS1||SS2", semester: "1st Term", year: "2nd Year", subjectCode: "S3", units: "9" }],
        callback = function (o) { return { Corequisites: o.corequisite ? o.corequisite.split('||') : [], Prequisites: o.prerequisites ? o.prerequisites.split('||') : [], subjectCode: o.subjectCode }; },
        result1 = getGrouped(data, [{ year: 'Year' }, { semester: 'term' }], callback, ['Sem', 'subjects']),
        result2 = getGrouped(data, [['curriculumYr', 'programCode', 'majorCode'], { semester: 'term' }], callback, ['Sem', 'subjects']);
    
    console.log(result1);
    console.log(result2);
    .as-console-wrapper { max-height: 100% !important; top: 0; }