Combine two arrays into Array of objects, counting up duplicates

489 Views Asked by At

I'm trying to combine two arrays into an array of objects and I'm struggling with that.

Example:

arr1 = [a,b,c];
arr2 = [a,a,a,b,b,c,d,d];

The way I'd like to have these two combined:

combinedArr = [
    {name: a, amount: 3}, 
    {name: b, amount: 2}, 
    {name: c, amount: 1}
];

Note that only values stored in arr1 should be integrated, any arr2 values non-existent in arr1 are just left out. (in this example, it's "d")

Also important to know is that I'm using this for After Effect's Extendscript which limits me to the 3rd Edition of the ECMA-262 Standard, leaving me with good old classic javascript. Functionalities like concat, slice and join are not available.

I've tried my way around but I can't figure it out.. I'm sure its possible to achieve a solution with just two or three smart loops through the arrays.

Thanks in advance, Simon

EDIT: I have created confusion by not adding my own attempts at my problem. I'm sorry I didn't, I've been thinking about it overnight and wrote this question on my phone on the train.

I've already received amazing answers that I'm very happy about, just to prove I had no ill meaning about my question, I'll post what I had written before (not simplified, but from the actual code):

var createMarkerList = function() {
    var subList = _createMarkerListSub(); //in this example arr1
    var masterList = _createMarkerListMaster(); //in this example arr2
    var output = [];

    for(var i=0;i<subList.length;i++){
        var uniqueMarker = subList[i];
        output.push({
            name: uniqueMarker,
            amount: 0,
        });
    }

    for(var i=0;i<masterList.length;i++){
        var genericMarker = masterList[i];

        if(output[i].name == genericMarker){
            output[i].amount = output[i].amount +1;
        }
    }
}

Please note that I did't try to get the easy way around by just asking you for the answer without trying to figure it out, I simply couldn't get my head around it for some reason.

2

There are 2 best solutions below

7
On

you will have to iterate over both arrays and keep a count of all elements in arr1.

var arr1 = ['a','b','c'];
var arr2 = ['a','a','a','b','b','c','d','d'];
var combinedObject= {}, combinedArray = [];
for(var i=0; i<arr1.length; i++)
   combinedObject[arr1[i]] = 0;

for(var i=0; i<arr2.length; i++)
   if(combinedObject.hasOwnProperty(arr2[i]))
 combinedObject[arr2[i]]++;

for(var key in combinedObject)
   combinedArray.push({'name': key, 'amount':combinedObject[key]});

console.log(combinedArray);

1
On

You could use a hash table and use it for counting.

You need to loop over arr1 tocreate the hash table and the result set and a second loop over the item to count and increment the amount property.

var arr1 = ['a', 'b', 'c'],
    arr2 = ['a', 'a', 'a', 'b', 'b', 'c', 'd', 'd'],
    hash = {},
    result = [],
    i;
    
for (i = 0; i < arr1.length; i++) {
    hash[arr1[i]] = { name: arr1[i], amount: 0 };
    result.push(hash[arr1[i]]);
}

for (i = 0; i < arr2.length; i++) {
    hash[arr2[i]] && hash[arr2[i]].amount++;
}

console.log(result);