将两个数组与对象合并

Merge two arrays with objects

我打算合并两个对象:

var c = {
    name: "doo",
    arr: [
        {
            id: 1,
            ver: 1
        },
        {
            id: 3,
            ver: 3
        }
    ]
};


var b = {
    name: "moo",
    arr: [
        {
            id: 1,
            ver: 0
        },
        {
            id: 2,
            ver: 0
        }
    ]
};

当使用 Object.assign({},b,c) 时,b.arr 被简单地替换为 c.arr。

我的问题是,如何保留 b.arr 中不在 c.arr 中的对象,但在匹配 b.arr[0].id === c.arr[0].id 时仍然合并该数组中的对象。期望的结果如下所示:

{
    name: "doo",
    arr: [
        {
            id: 1,
            ver: 1
        },
        {
            id: 2,
            ver: 0
        },
        {
            id: 3,
            ver: 3
        }
    ]
}

谢谢。

您可以从 apache commons

查看 ArrayUtils.addAll()

试试这个函数:

function mergeArrayObjects (a, b) {
    var tmp, // Temporary array that will be returned
        // Cache values
        i = 0,
        max = 0;

    // Check if a is an array
    if ( typeof a !== 'object' || typeof a.indexOf === 'undefined')
        return false;
    // Check if b is an array
    if ( typeof b !== 'object' || typeof b.indexOf === 'undefined')
        return false;

    // Populate tmp with a
    tmp = a;

    // For each item in b, check if a already has it. If not, add it.
    for (i = 0, max = b.length; i < max; i++) {
        if (tmp.indexOf(b[i]) === -1)
            tmp.push(b[i]);
    }
    // Return the array
    return tmp;
}

JsFiddle here

注意:因为我是anal,所以我决定看看这个函数是否比建议的替代方法更快。 It is.

只要您使用 lodash - 您就可以组合使用 lodash 的功能。它可能看起来有点复杂,但事实并非如此:

_.assign({}, b, c, function(objectValue, sourceValue, key, object, source) {
  //merging array - custom logic
  if (_.isArray(sourceValue)) {
    //if the property isn't set yet - copy sourceValue
    if (typeof objectValue == 'undefined') {
      return sourceValue.slice();
    } else if (_.isArray(objectValue)) {
      //if array already exists - merge 2 arrays
      _.forEach(sourceValue, function(sourceArrayItem) {
        //find object with the same ID's
        var objectArrayItem = _.find(objectValue, {id: sourceArrayItem.id});
        if (objectArrayItem) {
          //merge objects
          _.assign(objectArrayItem, sourceArrayItem);
        } else {
          objectValue.push(sourceArrayItem);
        }
      });
      return objectValue;
    }
  }
  //if sourceValue isn't array - simply use it
  return sourceValue;
});

查看完整演示 here

使用 lodash,我会做这样的事情:

var first = {
    name: 'doo',
    arr: [
        { id: 1, ver: 1 },
        { id: 3, ver: 3 }
    ]
};

var second = {
    name: 'moo',
    arr: [
        { id: 1, ver: 0 },
        { id: 2, ver: 0 }
    ]
};

_.merge(first, second, function(a, b) { 
    if (_.isArray(a)) {
        return _.uniq(_.union(a, b), 'id');
    } else {
        return a;
    }
});

// →
// {
//   name: 'doo',
//   arr: [
//     { id: 1, ver: 1 },
//     { id: 2, ver: 0 },
//     { id: 3, ver: 3 }
//   ]
// }

merge() function let's you specify a customizer callback for things like arrays. So we just need to check it it's an array we're dealing with, and if so, use the uniq() and union() 函数通过 id 属性 查找唯一值。