将两个数组与对象合并

时间:2015-03-24 15:11:40

标签: javascript arrays merge extend lodash

我计划合并两个对象:

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
        }
    ]
}

感谢。

4 个答案:

答案 0 :(得分:2)

你可以从apache commons看看ArrayUtils.addAll()

答案 1 :(得分:1)

只要您使用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

答案 2 :(得分:0)

尝试此功能:

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

注意:因为我是肛门,我决定看看这个功能是否比提议的更快。 It is.

答案 3 :(得分:0)

使用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()函数允许您为数组之类的内容指定自定义程序回调。所以我们只需要检查它是否是我们正在处理的数组,如果是,请使用uniq()union()函数通过{{1}查找唯一值属性。