3

I want to merge two A3 Objects together which contain some of the same Keys but different values. I've found many posts regarding adding two Objects together but I want to merge the two objects together so if the second object has different values they take priority. I have two Objects below:

    _propsObj =  new Object();
    _propsObj.baseColour = 0x303237;
    _propsObj.animation = false;
    _propsObj.font = "Verdana";
    _propsObj.fontColour = 0xffffff;
    _propsObj.baseFontSize = 14;    

    _propsObj2 =  new Object();
    _propsObj2.animation = true;        
    _propsObj2.fontColour = 0xffffff;
    _propsObj2.baseFontSize = 10;   

My desired ouput Object would accept the new values of the second Object but maintain the values of the first Object :

    _outputObj.baseColour = 0x303237;
    _outputObj.animation = true;
    _outputObj.font = "Verdana";
    _outputObj.fontColour = 0xffffff;
    _outputObj.baseFontSize = 10;   

I wasn't sure if I should be using Arrray.concat do this or if there is an easier solution? Any help would be appreciated.

5 Answers 5

3

the merge method hereunder

    var _propsObj:Object =  new Object();
    _propsObj.baseColour = 0x303237;
    _propsObj.animation = false;
    _propsObj.font = "Verdana";
    _propsObj.fontColour = 0xffffff;
    _propsObj.baseFontSize = 14;    

    var _propsObj2:Object =  new Object();
    _propsObj2.animation = true;        
    _propsObj2.fontColour = 0xffffff;
    _propsObj2.baseFontSize = 10;   
        
    var merged:Object = merge( _propsObj, _propsObj2 );
        
    private function merge( obj0:Object, obj1:Object ):Object
    {
        var obj:Object = { };
        for( var p:String in obj0 )
        {
            obj[ p ] = ( obj1[ p ] != null ) ? obj1[ p ] : obj0[ p ];
            trace( p, ' : obj0', obj0[ p ], 'obj1', obj1[ p ], '-> new value = ', obj[ p ] );
        }
        return obj;
    }
    

traces:

font : obj0 Verdana obj1 undefined -> new value = Verdana

fontColour : obj0 16777215 obj1 16777215 -> new value = 16777215

baseColour : obj0 3158583 obj1 undefined -> new value = 3158583

animation : obj0 false obj1 true -> new value = true

baseFontSize : obj0 14 obj1 10 -> new value = 10

the important line is :

obj[ p ] = ( obj1[ p ] != null ) ? obj1[ p ] : obj0[ p ];

it recursively creates the property on the new Object 'obj' and checks if that property is assigned on the 2nd object, if so it assigns the value of the second object to that property, otherwise it falls back to the value of that property on the first object.

NB: if a value is not set on the first object, it will not be looked up in the second object.

Sign up to request clarification or add additional context in comments.

1 Comment

that's what @bmleite also sugeested in a more compact way :)
3

You can use something like this:

private function merge(obj1:Object, obj2:Object):Object {
    var result:Object = new Object();
    for (var param:String in obj1) {
        result[param] = (obj2[param] ? obj2[param] : obj1[param]);
    }
    return result;
}

Usage:

_outputObj = merge(_propsObj, _propsObj2);

1 Comment

@Veehmot As far as I understood the intent was to merge only "different values" and not new properties. To do a "full" merge change the following line var result:Object = new Object(); to var result:Object = ObjectUtil.copy(obj2);. It's not optimal but works for most of the cases.
2

If you want to overwrite the existing values in the first object, you could just do this:

for ( var p in _propsObj2 )
    _propsObj[p] = _propsObj2[p];

Comments

1
var _propsObj:Object =  new Object();
_propsObj.baseColour = 0x303237;
_propsObj.animation = false;
_propsObj.font = "Verdana";
_propsObj.fontColour = 0xffffff;
_propsObj.baseFontSize = 14;    

var _propsObj2:Object =  new Object();
_propsObj2.animation = true;        
_propsObj2.fontColour = 0xffffff;
_propsObj2.baseFontSize = 10;

var mergedObj:Object = new Object();

//Adds the values from the first object
for (var r in _propsObj)
{
    mergedObj[r] = _propsObj[r];
}

//Adds the values from the second object
for(var s in _propsObj2)
{
    mergedObj[s] = _propsObj2[s];
}

//Checking the merged values
for(var t in mergedObj)
{
    trace([t, mergedObj[t]]);
}

Comments

1

Well, here's a generic utility function that does it:

public static function zip(objects:Array):Object
{
    var r:Object = {};

    for each (var o:Object in objects)
        for (var k:String in o)
            r[k] = o[k];

    return r;
}

Usage example:

var obj:Object = {
    "foo": 1,
    "bar": 2,
    "baz": 3
};

var obj2:Object = {
    "bar": 4,
    "baz": 6
};

var obj3:Object = {
    "foo": 3,
    "bar": 6
};

var result:Object = zip([obj, obj2, obj3]);

for (var k:String in result)
    trace("Property:", k, result[k]);

Output:

Property: foo 3
Property: baz 6
Property: bar 6

Side note: This is a "lossy" method in that the resultant object does not know where the individual properties came from and retains only the latest version of the value. If you want to preserve that information then there's another way to do this, using the prototype chain. It's how the Flex framework chains style settings, for example.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.