March 27, 2012

Join 2 arrays in object with repeated keys

Question by DannYO

I have 2 arrays of the same length like this:

a = [12,21,21,13,13,13,13,31];
b = [4,7,4,6,2,9,4,1];

The first array are the keys and the second array the values, but if the key is repeated the the values should be grouped in the corresponding key instead of being replaced.
The object should look like so:

o = {
    12: [4],
    21: [7,4],
    13: [6,2,9,4],
    31: [1]
}

And here what I tried:

var o = {};
for ( var index in a) {
    o[a[index]] = [];
    o[a[index]].push(b[index]);
}

Answer by T.J. Crowder

Don’t use for..in to loop through arrays (unless they’re sparse arrays and you know what you’re doing; details).

Other than that, you’re on the right track, but you have to check to see whether the array already exists before overwriting it. So:

var o = {}, key, entry;
for (index = 0; index < a.length; ++index) {
    // Get the key
    key = a[index];

    // Get the entry's array if it already exists
    entry = o[key];
    if (!entry) {
        // It doesn't exist, create it and remember it in the object
        o[key] = entry = [];
    }

    // Put this value in it
    entry.push(b[index]);
}

Or a couple of small optimizations:

var o = {}, key, entry, len;
for (index = 0, len = a.length; index < len; ++index) {
    // Get the key
    key = a[index];

    // Get the entry's array if it already exists
    entry = o[key];
    if (!entry) {
        // It doesn't exist, create it and remember it in the object,
        // including this value as we go
        o[key] = [b[index]];
    }
    else {
        // Already existed, add this value to it
        entry.push(b[index]);
    }
}

If you’re using an ES5-enabled environment (or you include an ES5 shim), you can use forEach:

var o = {};
a.forEach(function(key, index) {
    var entry;

    // Get the entry's array if it already exists
    entry = o[key];
    if (!entry) {
        // It doesn't exist, create it and remember it in the object,
        // including this value as we go
        o[key] = [b[index]];
    }
    else {
        // Already existed, add this value to it
        entry.push(b[index]);
    }
});

Answer by Starx

Here is a function you can use from phpjs.com for this

function array_combine (keys, values) {
    // Creates an array by using the elements of the first parameter as keys and the elements of the second as the corresponding values  
    var new_array = {},        keycount = keys && keys.length,
        i = 0;

    // input sanitation
    if (typeof keys !== 'object' || typeof values !== 'object' || // Only accept arrays or array-like objects    typeof keycount !== 'number' || typeof values.length !== 'number' || !keycount) { // Require arrays to have a count
        return false;
    }

    // number of elements does not match    if (keycount != values.length) {
        return false;
    }

    for (i = 0; i < keycount; i++) {        new_array[keys[i]] = values[i];
    }

    return new_array;
}

Author: Nabin Nepal (Starx)

Hello, I am Nabin Nepal and you can call me Starx. This is my blog where write about my life and my involvements. I am a Software Developer, A Cyclist and a Realist. I hope you will find my blog interesting. Follow me on Google+

...

Please fill the form - I will response as fast as I can!