Javascript:合并两个对象数组,只有在不重复的情况下(基于指定的对象键)

And*_*cer 3 javascript arrays

背景

假设我有一个初始的对象数组:

var initialData = [
    {
        'ID': 1,
        'FirstName': 'Sally'
    },
    {
        'ID': 2,
        'FirstName': 'Jim'
    },
    {
        'ID': 3,
        'FirstName': 'Bob'
    }
];
Run Code Online (Sandbox Code Playgroud)

然后,我得到新数据(对象的另一个数组):

var newData = [
    {
        'ID': 2,
        'FirstName': 'Jim'
    },
    {
        'ID': 4,
        'FirstName': 'Tom'
    },
    {
        'ID': 5,
        'FirstName': 'George'
    }
];
Run Code Online (Sandbox Code Playgroud)

目标

我想将新数据合并为初始数据。但是,我不想覆盖初始数据数组中的任何对象。我只想添加尚未存在的对象。

我知道对象是根据其'ID'键重复的。

我尝试过的

我知道我可以通过遍历新数据,检查它是否存在于初始数据中,如果不存在则推入初始数据来做到这一点。

for ( var i = 0, l = newData.length; i < l; i++  ) {

    if ( ! key_exists( newData[i].key, initialData ) ) {  // key_exists() is a function that uses .filter() to test.

        initialData.push( newData[i] );

    }


}
Run Code Online (Sandbox Code Playgroud)

不过,我担心性能。我知道有许多新的ES6处理数组的方式,所以我希望有人有更好的主意。

在忽略新数据中的重复项的同时,将新数据合并到初始数据中的最佳方法(最佳与最佳性能)是什么?

sli*_*der 8

您可以从中创建一组ID initialData,这将使“检查ID是否已在初始数据中”更快-O(1):

var initialData = [{
    'ID': 1,
    'FirstName': 'Sally'
  },
  {
    'ID': 2,
    'FirstName': 'Jim'
  },
  {
    'ID': 3,
    'FirstName': 'Bob'
  }
];

var newData = [{
    'ID': 2,
    'FirstName': 'Jim'
  },
  {
    'ID': 4,
    'FirstName': 'Tom'
  },
  {
    'ID': 5,
    'FirstName': 'George'
  }
];

var ids = new Set(initialData.map(d => d.ID));
var merged = [...initialData, ...newData.filter(d => !ids.has(d.ID))];

console.log(merged);
Run Code Online (Sandbox Code Playgroud)

该方法的最终运行时间为O(n + m)

如果您想提高效率,可以考虑newData手动遍历并将所有新元素推送到最终结果数组中(而不是使用filter和运算符)。

  • Nit:另一个可能的性能改进是使用连接而不是扩展。有信息表明 concat 速度更快一些。/sf/ask/3420599731/ (2认同)