如何基于属性(不是索引)合并2个数组 [英] how to merge 2 arrays based on properties (not index)

查看:103
本文介绍了如何基于属性(不是索引)合并2个数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们知道,jQuery.extend(true, obj1, obj2)方法用于将对象的属性从obj2深度复制到obj1.如果是数组,它将根据索引复制属性.但是我需要根据以下示例基于某些属性(例如本例中的id)进行复制:

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 need copying based on some property (e.g. id in my case) as per following example:

obj1 = [{id:"id1", name:"name1"},{id:"id2", name:"name2"}]
obj2 = [{id:"id3", name:"name3"}{id:"id1", name:"name1_modified"}]

jQuery.extend将返回:

[{id:"id3", name:"name3"}{id:"id1", name:"name1_modified"}]

但是我需要输出为:

[{id:"id1", name:"name1_modified"},{id:"id2", name:"name2"}{id:"id3", name:"name3"}]

有什么方法/图书馆可以做到这一点吗?

is there any method/library to accomplish this?

推荐答案

在处理我的项目时,我遇到了同样的问题.所以我jquery扩展以基于其属性完成数组合并.如果要基于属性合并数组,请在合并函数中将属性名称作为最后一个参数传递.我已经创建了 jsfiddle ,请在浏览器控制台中查看结果.

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"));​

这篇关于如何基于属性(不是索引)合并2个数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆