Merging objects (associative arrays)

JavascriptObject

Javascript Problem Overview


What’s the best/standard way of merging two associative arrays in JavaScript? Does everyone just do it by rolling their own for loop?

Javascript Solutions


Solution 1 - Javascript

with jquery you can call $.extend

var obj1 = {a: 1, b: 2};
var obj2 = {a: 4, c: 110};

var obj3 = $.extend(obj1, obj2); 

obj1 == obj3 == {a: 4, b: 2, c: 110} // Pseudo JS

(assoc. arrays are objects in js)

look here: http://api.jquery.com/jQuery.extend/


edit: Like rymo suggested, it's better to do it this way:

obj3 = $.extend({}, obj1, obj2); 
obj3 == {a: 4, b: 2, c: 110}

As here obj1 (and obj2) remain unchanged.


edit2: In 2018 the way to do it is via Object.assign:

var obj3 = Object.assign({}, obj1, obj2); 
obj3 === {a: 4, b: 2, c: 110} // Pseudo JS

If working with ES6 this can be achieved with the Spread Operator:

const obj3 = { ...obj1, ...obj2 };

Solution 2 - Javascript

Now in 2016 I would say the best/standard way is Object.assign()
Pure Javascript. No jQuery is needed.

obj1 = {a: 1, b: 2};
obj2 = {a: 4, c: 110};
obj3 = Object.assign({},obj1, obj2);  // Object {a: 4, b: 2, c: 110}

More information, examples and polyfill here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Solution 3 - Javascript

This is how Prototype does it:

Object.extend = function(destination, source) {
	for (var property in source) {
        if (source.hasOwnProperty(property)) {
            destination[property] = source[property];
        }
    }
	return destination;
};

called as, for example:

var arr1 = { robert: "bobby", john: "jack" };
var arr2 = { elizabeth: "liz", jennifer: "jen" };

var shortnames = Object.extend(arr1,arr2);

EDIT: added hasOwnProperty() check as correctly pointed out by bucabay in comments

Solution 4 - Javascript

Keep it simple...

function mergeArray(array1,array2) {
  for(item in array1) {
    array2[item] = array1[item];
  }
  return array2;
}

Solution 5 - Javascript

Underscore also has an extend method:

> Copy all of the properties in the source objects over to the > destination object. It's in-order, so the last source will override > properties of the same name in previous arguments.

_.extend(destination, *sources) 

_.extend({name : 'moe'}, {age : 50});
=> {name : 'moe', age : 50}

Solution 6 - Javascript

In dojo, the 2-objects/arrays "merge" would be lang.mixin(destination, source) -- you can also mix multiple sources into one destination, etc -- see the mixin function's reference for details.

Solution 7 - Javascript

do you want to overwrite a property if the names are the same but the values are not?

And do you want to permanently change one of the original objects,

or do you want a new merged object returned?

function mergedObject(obj1, obj2, force){
	for(var p in obj1) this[p]= obj1[p];
	for(var p in obj2){
		if(obj2.hasOwnProperty(p)){
			if(force || this[p]=== undefined) this[p]= obj2[p];
			else{
				n= 2;
				while(this[p+n]!== undefined)++n;
				this[p+n]= obj2[p];
			}
		}
	}
}

Solution 8 - Javascript

Rolling Your Own Extend/Mixin Function

function extend(objects) {
    var args
        , first = Array.prototype.slice.call(arguments, 0, 1)[0]
        , second;

    if (arguments.length > 1) {
        second = Array.prototype.splice.call(arguments, 1, 1)[0];
        for (var key in second) {
            first[key] = second[key];
        }
        args = Array.prototype.slice.call(arguments, 0);
        return extend.apply(this, args);
    }

    return first;
}

...

var briansDirections = {
    step1: 'Remove pastry from wrapper.',
    step2: 'Place pastry toaster.',
    step3: 'Remove pastry from toaster and enjoy.',
};
extend(briansDirections, { step1: 'Toast Poptarts' }, { step2: 'Go ahead, toast \'em' }, { step3: 'Hey, are you sill reading this???' });

...

This simply extends a splat of objects, recursively. Also, note that this recursive function is TCO (Tail-Call Optimized) as its return is the last call to itself.

Additionally, you may want targeted properties. In this case, you may want to condense objects based upon id, quantity, or another property. This approach could have a small book written about it and requires object-juxtaposition and can get very complex. I've written a small library for this which is available upon request.

Hope this helps!

Solution 9 - Javascript

  1. In Javascript there is no notion of associative array, there are objects
  2. The only way to merge two objects is to loop for their properties and copy pointers to their values that are not primitive types and values for primitive types to another instance

Solution 10 - Javascript

In 2019 you have 2 good options:

Object assigning [doc]

const result = Object.assign({}, baseObject, updatingObject);

Object spreading [doc]

const result = { ...baseObject, ...updatingObject};

The first one tends to be safer, more standard and polyvalent. A good pros and cons here

Solution 11 - Javascript

Yahoo UI (YUI) also has a helper function for this:

http://developer.yahoo.com/yui/examples/yahoo/yahoo_merge.html

YAHOO.namespace('example');

YAHOO.example.set1 = { foo : "foo" };
YAHOO.example.set2 = { foo : "BAR", bar : "bar" };
YAHOO.example.set3 = { foo : "FOO", baz : "BAZ" };

var Ye = YAHOO.example;

var merged = YAHOO.lang.merge(Ye.set1, Ye.set2, Ye.set3);

Solution 12 - Javascript

jquery has a boolean for deep copy. You could do something like that:

MergeRecursive = function(arr1, arr2){
    $.extend(true, arr1, arr2);
    return arr1;				
};

Also you can edit this function to support n-arrays to merge.

ArrayMergeRecursive = function(){
     if(arguments.length < 2){
          throw new Error("ArrayMergeRecursive: Please enter two or more objects to merge!");
     }

    var arr1=arguments[0];
    for(var i=0; i<=arguments.length; i++ ){
        $.extend(true, arr1, arguments[i]);					
    }

    return arr1;				
};

So now you can do

var arr1 = {'color': {'mycolor': 'red'}, 3: 5},
    arr2 = {4: 10, 'color': {'favorite': 'green', 0: 'blue'}},
    arr3 = ['Peter','Jhon','Demosthenes'],
    results = ArrayMergeRecursive(arr1, arr2, arr3); // (arr1, arr2 ... arrN)
console.log("Result is:", results);

Solution 13 - Javascript

I needed a deep-object-merging. So all of the other answers didn't help me very much. _.extend and jQuery.extend do well, unless you have a recursive array like i do. But it ain't so bad, you can program it in five minutes:

var deep_merge = function (arr1, arr2) {
    jQuery.each(arr2, function (index, element) {
        if (typeof arr1[index] === "object" && typeof element === "object") {
            arr1[index] = deep_merge(arr1[index], element);
        } else if (typeof arr1[index] === "array" && typeof element === "array") {
            arr1[index] = arr1[index].concat(element);
        } else {
            arr1[index] = element;
        }
    });
    return arr1;
}

Solution 14 - Javascript

To merge arrays in jQuery what about $.merge?

var merged = $.merge([{id:3, value:'foo3'}], [{id:1, value:'foo1'}, {id:2, value:'foo2'}]);
merged[0].id == 3;
merged[0].value == 'foo3';
merged[1].id == 1;
merged[1].value == 'foo1';
merged[2].id == 2;
merged[2].value == 'foo2';

Solution 15 - Javascript

Recursive solution (extends also arrays of objects) + null checked

var addProps = function (original, props) {
    if(!props) {
        return original;
    }
    if (Array.isArray(original)) {
        original.map(function (e) {
            return addProps(e, props)
        });
        return original;
    }
    if (!original) {
        original = {};
    }
    for (var property in props) {
        if (props.hasOwnProperty(property)) {
            original[property] = props[property];
        }
    }
    return original;
};

Tests

console.log(addProps([{a: 2}, {z: 'ciao'}], {timestamp: 13}));
console.log(addProps({single: true}, {timestamp: 13}));
console.log(addProps({}, {timestamp: 13}));
console.log(addProps(null, {timestamp: 13}));

[ { a: 2, timestamp: 13 }, { z: 'ciao', timestamp: 13 } ]
{ single: true, timestamp: 13 }
{ timestamp: 13 }
{ timestamp: 13 }

Solution 16 - Javascript

Here is the best solution.

obj1.unshift.apply( obj1, obj2 );

Also, obj1 can grow inside a loop without any problem. (lets say obj2 is dynamic)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWilhelmView Question on Stackoverflow
Solution 1 - JavascriptkulpaeView Answer on Stackoverflow
Solution 2 - JavascriptManfredView Answer on Stackoverflow
Solution 3 - JavascriptJonathan FinglandView Answer on Stackoverflow
Solution 4 - JavascriptChris ScerboView Answer on Stackoverflow
Solution 5 - JavascriptMike McKayView Answer on Stackoverflow
Solution 6 - JavascriptAlex MartelliView Answer on Stackoverflow
Solution 7 - JavascriptkennebecView Answer on Stackoverflow
Solution 8 - JavascriptCodyView Answer on Stackoverflow
Solution 9 - JavascriptSergey IlinskyView Answer on Stackoverflow
Solution 10 - JavascriptVincentPerrin.comView Answer on Stackoverflow
Solution 11 - JavascriptBen WaldingView Answer on Stackoverflow
Solution 12 - JavascriptdemosthenesView Answer on Stackoverflow
Solution 13 - JavascriptRasmusView Answer on Stackoverflow
Solution 14 - JavascriptRogério R. AlcântaraView Answer on Stackoverflow
Solution 15 - JavascriptsscarduzioView Answer on Stackoverflow
Solution 16 - JavascriptbilenView Answer on Stackoverflow