Skip to content
Advertisement

Iterate nested array items and, upon the same value of a specific key, collect any other entry value as data of a merger which is grouped by key+value

I have an array that looks like this:

enter image description here

So as a strucutre it would be something like:

[
    [
       { classNumber: '2', status: 'A', terms: [] }, 
       { classNumber: '32', status: 'B', terms: [] }, 
       { classNumber: '44', status: 'C', terms: []  }
    ],
    [
        { classNumber: '2', status: 'B', terms: [] }, 
        { classNumber: '31', status: 'A', terms: [] }
    ],
    ....
]

This wierd array of objects happens because at some point, in our app, we are creating an array of reasons to object something using the same object.

I need to be able to merge the nested array of objects to look like this:

[
     { classNumber: '2', status: [ 'A', 'B' ], terms: [] }, 
     { classNumber: '31', status: [ 'A' ], terms: [] }, 
     { classNumber: '32', status: [ 'B' ], terms: [] }, 
     { classNumber: '44', status: [ 'C' ], terms: [] }
]

But I’ve been struggling with this for some days, looking for some lodash functions but still no luck…

I’m completely lost on how to achieve this. All examples look simpler, with less nested arrays. Any idea on how to merge all props for the same object key?

Thanks a lot in advance.

Answer

If I’m not missing something, you are looking for this:?

var merged = Array.prototype.concat.apply([], original);

like:

Array.prototype.concat.apply([], [[1,2,3],[4,5], [6]]);
// returns:
// [1, 2, 3, 4, 5, 6]

Another way:

var merged = [];
for(var i = 0; i<original.length; i++) {
  for(var j = 0, arr = original[i]; j<arr.length; j++) {
    merged.push(arr[j]);
  }
}
    

update:

Yes, I DO HAVE MISSED SOMETHING. Thanks @PeterSeliger for pointing it out. But instead of delete this answer, I’d like to update and correct it.

The code below is NOT TESTED.

function doMergeItems(prev, current) {
  // Merge content of "current" with "prev"
  // Below is just a simple example, need to be replaced
  // according to the desired merging strategy.
  if(!prev)
    prev = {
      classNumber: current.classNumber,
      status: [],
      terms: [],
    };
  prev.status.push(current.status);
  prev.terms.push(...current.terms);
  return prev;
}


var merged = [];
for(var i = 0; i<original.length; i++) {
  for(var j = 0, arr = original[i]; j<arr.length; j++) {
    var item = arr[j];
    var index = merged.findIndex(function(x){
      return x.classNumber === item.classNumber;
    });
    if(index < 0)
      merged.push(doMergeItems(null, item));
    else
      merged[index] = doMergeItems(merged[index], item);
  }
}

Advertisement