How do I merge an array of objects in Javascript?

前端 未结 3 1695
我寻月下人不归
我寻月下人不归 2020-12-20 23:19

Example:

var array1 = [ {\'key\':1, \'property1\': \'x\'}, {\'key\':2, \'property1\': \'y\'} ]
var array2 = [ {\'key\':2, \'property2\': \'a\'}, {\'key\':1,          


        
3条回答
  •  温柔的废话
    2020-12-20 23:33

    I wrote a quick not-so-quick solution. The one problem you might want to consider is whether a property from an object in the second array should override the same property, if present, in the second object it's being compared to.

    Solution 1

    This solution is of complexity O(n²). Solution 2 is much faster; this solution is only for those who don't want to be Sanic the Hedgehog fast.

    JavaScript

    var mergeByKey = function (arr1, arr2, key) {
    // key is the key that the function merges based on
        arr1.forEach(function (d, i) {
            var prop = d[key];
            // since keys are unique, compare based on this key's value
            arr2.forEach(function (f) {
                if (prop == f[key]) {    // if true, the objects share keys
                    for (var x in f) {   // loop through each key in the 2nd object
                        if (!(x in d))   // if the key is not in the 1st object
                            arr1[i][x] = f[x];    // add it to the first object
                    // this is the part you might want to change for matching properties
                    // which object overrides the other?
                    }
                }
            })
        })
        return arr1;
    }
    

    Test Case

    var arr = [ {'key':1, 'property1': 'x'},
                {'key':2, 'property1': 'y'} ],
        arr2= [ {'key':2, 'property2': 'a'},
                {'key':1, 'property2': 'b'} ];
    
    console.log(mergeByKey(arr, arr2, "key"));
    

    Results

    /* returns:
        Object
        key: 1
        property1: "x"
        property2: "b"
        __proto__: Object
    and 
        Object
        key: 2
        property1: "y"
        property2: "a"
        __proto__: Object
    */
    

    fiddle

    Solution 2

    As Vivin Paliath pointed out in the comments below, my first solution was of O(n²) complexity (read: bad). His answer is very good and provides a solution with a complexity of O(m + n), where m is the size of the first array and n of the second array. In other words, of complexity O(2n).

    However, his solution does not address objects within objects. To solve this, I used recursion—read: the devil, just like O(n²).

    JavaScript

    var mergeByKey = function (arr1, arr2, key) {
        var holder = [],
            storedKeys = {},
            i = 0; j = 0; l1 = arr1.length, l2 = arr2.length;
    
        var merge = function (obj, ref) {
            for (var x in obj) {
                if (!(x in ref || x instanceof Object)) {
                    ref[x] = obj[x];
                } else {
                    merge(obj[x], ref[x]);
                }
            }
            storedKeys[obj.key] = ref;
        }
        for (; i < l1; i++) {
            merge(arr1[i], storedKeys[arr1[i].key] || {});
        }
        for (; j < l2; j++) {
            merge(arr2[j], storedKeys[arr2[j].key] || {});
        }
    
        delete storedKeys[undefined];
    
        for (var obj in storedKeys)
            holder.push(storedKeys[obj]);
    
        return holder;
    }
    

    Test Case

    var arr1 = [
        {
            "key" : 1,
            "prop1" : "x",
            "test" : {
                "one": 1,
                "test2": {
                    "maybe" : false,
                    "test3": { "nothing" : true }
                }
            }
        },
        {
            "key" : 2,
            "prop1": "y",
            "test" : { "one": 1 }
        }],
        arr2 = [
            {
                "key" : 1,
                "prop2" : "y",
                "test" : { "two" : 2 }
            },
            {
                "key" : 2,
                "prop2" : "z",
                "test" : { "two": 2 }
            }];
    console.log(mergeByKey(arr1, arr2, "key"));
    

    Results

    /*
    Object
        key: 1
        prop1: "x"
        prop2: "y"
        test: Object
            one: 1
            test2: Object
                maybe: false
                test3: Object
                    nothing: true
                    __proto__: Object
                __proto__: Object
            two: 2
            __proto__: Object
        __proto__: Object
    Object
        key: 2
        prop1: "y"
        prop2: "z"
        test: Object
            one: 1
            two: 2
            __proto__: Object
        __proto__: Object
    */
    

    This correctly merges the objects, along with all child objects. This solutions assumes that objects with matching keys have the same hierarchies. It also does not handle the merging of two arrays.

    fiddle

提交回复
热议问题