0

I have to do some calcucations based on inputArray and factorArray and create third array outputArray. You can see caclucations part in outputArray properties marks and noOfStudents based on the subject property

var inputArray = [
  { subject: 'Maths', marks: '40', noOfStudents: '5' },
  { subject: 'Science', marks: '50', noOfStudents: '16' },
  { subject: 'History', marks: '35', noOfStudents: '23' },
  { subject: 'Science', marks: '65', noOfStudents: '2' },
  { subject: 'Maths', marks: '30', noOfStudents: '12' },
  { subject: 'History', marks: '55', noOfStudents: '20' }
];

var factorArray = [
  { subject: 'History', marks: '500', noOfStudents: '200' },
  { subject: 'Maths', marks: '200', noOfStudents: '150' },
  { subject: 'Science', marks: '300', noOfStudents: '100' }      
];

var outputArray = [
    { subject: 'Science', marks: '300-(50+65)', noOfStudents: '100-(16+2)' },
    { subject: 'Maths', marks: '200-(40+30)', noOfStudents: '150-(5+12)' },
    { subject: 'History', marks: '500-(35+55)', noOfStudents: '200-(23+20)' }
 ];

I need to extend the solution to my previous question: https://stackoverflow.com/a/37481705

Community
  • 1
  • 1
SBP
  • 147
  • 1
  • 6

3 Answers3

1

This proposal uses a temp object, first for the result of the grouping of inputArray and later for the creation of outputArray. The complexity of this operation is linear O(n+m).

var inputArray = [{ subject: 'Maths', marks: '40', noOfStudents: '5' }, { subject: 'Science', marks: '50', noOfStudents: '16' }, { subject: 'History', marks: '35', noOfStudents: '23' }, { subject: 'Science', marks: '65', noOfStudents: '2' }, { subject: 'Maths', marks: '30', noOfStudents: '12' }, { subject: 'History', marks: '55', noOfStudents: '20' }],
    factorArray = [{ subject: 'History', marks: '500', noOfStudents: '200' }, { subject: 'Maths', marks: '200', noOfStudents: '150' }, { subject: 'Science', marks: '300', noOfStudents: '100' }],
    temp = Object.create(null),
    outputArray = [];

inputArray.forEach(function (a) {
    this[a.subject] = this[a.subject] || { marks: [], noOfStudents: [] };
    this[a.subject].marks.push(a.marks);
    this[a.subject].noOfStudents.push(a.noOfStudents);
}, temp);

outputArray = factorArray.map(function (a) {
    var getSum = function (k) {
        return this[a.subject] && this[a.subject][k].length ? '-(' + this[a.subject][k].join('+') + ')' : '';
    }.bind(this);
    return { subject: a.subject, marks: a.marks + getSum('marks'), noOfStudents: a.noOfStudents + getSum('noOfStudents') };
}, temp);

console.log(outputArray);

Result with calculated items

var inputArray = [{ subject: 'Maths', marks: '40', noOfStudents: '5' }, { subject: 'Science', marks: '50', noOfStudents: '16' }, { subject: 'History', marks: '35', noOfStudents: '23' }, { subject: 'Science', marks: '65', noOfStudents: '2' }, { subject: 'Maths', marks: '30', noOfStudents: '12' }, { subject: 'History', marks: '55', noOfStudents: '20' }],
    factorArray = [{ subject: 'History', marks: '500', noOfStudents: '200' }, { subject: 'Maths', marks: '200', noOfStudents: '150' }, { subject: 'Science', marks: '300', noOfStudents: '100' }],
    temp = Object.create(null),
    outputArray = [];

inputArray.forEach(function (a) {
    this[a.subject] = this[a.subject] || { marks: 0, noOfStudents: 0 };
    this[a.subject].marks += +a.marks;
    this[a.subject].noOfStudents += +a.noOfStudents;
}, temp);

outputArray = factorArray.map(function (a) {
    var getSum = function (k) {
        return (+a[k] - (this[a.subject] && this[a.subject][k] || 0)).toString();
    }.bind(this);
    return { subject: a.subject, marks: getSum('marks'), noOfStudents: getSum('noOfStudents') };
}, temp);

console.log(outputArray);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

If subject in factorArray is unique:

var inputArray = [
  { subject: 'Maths', marks: '40', noOfStudents: '5' },
  { subject: 'Science', marks: '50', noOfStudents: '16' },
  { subject: 'History', marks: '35', noOfStudents: '23' },
  { subject: 'Science', marks: '65', noOfStudents: '2' },
  { subject: 'Maths', marks: '30', noOfStudents: '12' },
  { subject: 'History', marks: '55', noOfStudents: '20' }
];

var factorArray = [
  { subject: 'History', marks: '500', noOfStudents: '200' },
  { subject: 'Maths', marks: '200', noOfStudents: '150' },
  { subject: 'Science', marks: '300', noOfStudents: '100' }      
];

// the result
var outputArray = [];

// loop through the factors
for(var i = 0, numFactors = factorArray.length; i < numFactors; ++i) {
  // this iteration
  var thisFactor = factorArray[i];
  
  // make a copy
  var thisOutput = {
    "subject" : thisFactor.subject,
    "marks" : thisFactor.marks,
    "noOfStudents" : thisFactor.noOfStudents
  };
  
  // loop through the input
  for(var j = 0; j < inputArray.length; ++j) {
    // this iteration
    var thisInput = inputArray[j];
    
    // if the subject matches
    if(thisInput.subject == thisOutput.subject) {
      // do the calculation
      thisOutput.marks -= thisInput.marks;
      thisOutput.noOfStudents -= thisInput.noOfStudents;
      
      // we don't need to loop through this one again so remove it from the inputArray
      // and decrease j so we check it again on the "next" iteration
      inputArray.splice(j--, 1);
    }
  }
  
  // save it
  outputArray.push(thisOutput);
}

console.log(outputArray);
IMTheNachoMan
  • 5,343
  • 5
  • 40
  • 89
0

I would prefer doing by cascaded reduces like

var inar = [{ subject: 'Maths', marks: '40', noOfStudents: '5' },{ subject: 'Science', marks: '50', noOfStudents: '16' },{ subject: 'History', marks: '35', noOfStudents: '23' },{ subject: 'Science', marks: '65', noOfStudents: '2' },{ subject: 'Maths', marks: '30', noOfStudents: '12' },{ subject: 'History', marks: '55', noOfStudents: '20' }],
   facar = [{ subject: 'History', marks: '500', noOfStudents: '200' },{ subject: 'Maths', marks: '200', noOfStudents: '150' },{ subject: 'Science', marks: '300', noOfStudents: '100' }];

   outar = inar.reduce((p,c) => {var f = p.find(o => o.subject === c.subject);
                                 f ? (f.marks = f.marks*1 + c.marks*1,
                                      f.noOfStudents = f.noOfStudents*1 + c.noOfStudents*1)
                                   : p.push(c);
                            return p},[])
               .reduce((p,c) => {var f = p.find(o => o.subject === c.subject);
                                 f.marks = f.marks*1 - c.marks*1;
                                 f.noOfStudents = f.noOfStudents*1 - c.noOfStudents*1;
                                 return p},facar);
console.log(outar);
Redu
  • 25,060
  • 6
  • 56
  • 76