Javascript Nested Loop Pushing to Array

Viewed 1856

I am relatively new to programming and am having some issues with a project I am working on.

msg.newCG2 = [];
for(i=0;i<msg.newCG.length;i++){
    for(j=0;j<msg.campaignGroup.length;i++){
        if(msg.campaignGroup[j].col10 === msg.newCG[j]){
            msg.groupTotals = msg.groupTotals + msg.campaignGroup[j].col11;
    }
    msg.newCG2.push(msg.newCG[i], msg.groupTotals)
    }
}

Basically, for each one of the "IDs" (integers) in msg.newCG, I want to look for each ID in msg.campaignGroup and sum up the totals for all listings with the same ID, from msg.campaignGroup.col11 - then push the ID and the totals to a new array - msg.newCG2.

When I run the code, the first item sent through processes, but grinds to a halt because of memory. I assume this is because of an error in my code.

Where did this code go wrong? I am sure that there are better ways to do this as a whole, but I am curious where I went wrong.

3 Answers

Rather than looping 1.2M times, it would be more efficient to use a single-pass over the 4000 campaign groups, grouping by id to create an array of totals for all ids -- I like using the reduce() function for this:

var cgMap = msg.campaignGroups.reduce(function(arr, grp) {
        var grpid = grp.col10;
        var count = grp.col11;
        var total = arr[grpid] || 0;
        arr[grpid] = total + count;
    },
[]);

I know, the reduce(...) function is not the easiest to grok, but it takes the second arg (the empty array) and passes it, along with each campaign group object in turn, to that inline function. The result should be a simple array of group totals (from col11), indexed by the group id (from col10).

Now, it's just a matter of returning the totals for those 300 ids found in msg.newCG -- and this map() function does that for us:

var cgOut = msg.newCG.map(function(gid) {
        return cgMap[gid];  // lookup the total by group id
    }
);

I've made some assumptions here, like the group ids are not terribly large integers, and are rather closely spaced (not too sparse). From the original code, I was not able to determine the format of the data you are wanting to return in msg.newCG2. The final push() function would append 2 integers onto the array -- the output group id and the total for that group. Having pairs of group ids and totals interleaved in a flat array is not a very useful data structure. Perhaps you meant to place the total value into an array, indexed by the group id? If so, you could re-write that line as: msg.newCG2[msg.newCG[i]] = msg.groupTotals;

Related