Skip to content Skip to sidebar Skip to footer

How To Merge 2 Arrays Based On Properties (not Index)

As we know that jQuery.extend(true, obj1, obj2) method for deep copying the object's properties from obj2 to obj1. In case of array, it copies the property based on index. But I ne

Solution 1:

I have faced same problem while working on my project. So I jquery extend to accomplish array merge based on its property. If you want to merge array based on property, pass property name as last parameter in merge function. I have create a jsfiddle, see result in browser console.

function merge() {
    var options, name, src, copy, copyIsArray, clone, targetKey, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false;
    var currentId = typeof arguments[length - 1] == 'string' ? arguments[length - 1] : null;
    if (currentId) {
        length = length - 1;
    }
    // Handle a deep copy situation
    if (typeof target === "boolean") {
        deep = target;
        target = arguments[1] || {};
        // skip the boolean and the target
        i = 2;
    }

    // Handle case when target is a string or something (possible in deep
    // copy)
    if (typeof target !== "object" && !jQuery.isFunction(target)) {
        target = {};
    }

    // extend jQuery itself if only one argument is passed
    if (length === i) {
        target = this;
        --i;
    }

    for (; i < length; i++) {
        // Only deal with non-null/undefined values
        if ((options = arguments[i]) != null) {
            // Extend the base object
            for (name in options) {
                if (!options.hasOwnProperty(name)) {
                    continue;
                }
                copy = options[name];
                var mm = undefined, src = undefined;
                if (currentId && jQuery.isArray(options) && jQuery.isArray(target)) {
                    for (mm = 0; mm < target.length; mm++) {
                        if (currentId && (isSameString(target[mm][currentId], copy[currentId]))) {
                            src = target[mm];
                            break;
                        }
                    }
                }
                else {
                    src = target[name];
                }

                // Prevent never-ending loop
                if (target === copy) {
                    continue;
                }
                targetKey = mm !== undefined ? mm : name;
                // Recurse if we're merging plain objects or arrays
                if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {
                    if (copyIsArray) {
                        copyIsArray = false;
                        clone = src && jQuery.isArray(src) ? src : [];

                    }
                    else {
                        clone = src && jQuery.isPlainObject(src) ? src : {};
                    }

                    // Never move original objects, clone them
                    if (currentId) {
                        target[targetKey] = merge(deep, clone, copy, currentId);
                    }
                    else {
                        target[targetKey] = merge(deep, clone, copy);
                    }

                    // Don't bring in undefined values
                }
                else if (copy !== undefined) {
                    target[targetKey] = copy;
                }
            }
        }
    }

    // Return the modified object
    return target;
};
 function isSameString (a , b){
        return a && b && String(a).toLowerCase() === String(b).toLowerCase();
    }
obj1 = [ {
    id : "id1",
    name : "name1"
}, {
    id : "id2",
    name : "name2"
} ]
obj2 = [ {
    id : "id3",
    name : "name3"
}, {
    id : "id1",
    name : "name1_modified"
} ];
console.log(merge(true, obj1, obj2, "id"));​

Post a Comment for "How To Merge 2 Arrays Based On Properties (not Index)"