Javascript 数组和对象:获取差异并合并它们

Javascript arrays and objects: Get differences and merge them

所以我有这样一个场景,我有一个 client-app 将数据(对象数组)发送到 server 然后将数据转发给连接到此服务器的其他客户端

client-app中,数据是不断变化的,意思是:数值变化,数组里面的新对象弹出,对象被移除,等等...

现在我希望 其他客户端 始终接收最新数据。而且因为我不希望 client-app 全新数据 推送到服务器,然后服务器转发 全新数据dataother clients,我决定让 client-app 只推送 changes(使用这个库:https://www.npmjs.com/package/deep-object-diff)。

其他客户端然后收到一个对象数组,其中只有实际更改的数据,因为他们知道以前的数据数组, 我希望他们 "merge" 更改数组与旧数据对象。

我的实际问题是合并。我不知道如何正确地做到这一点。特别是如果我有一个没有任何对象键的对象数组。

所以我的数据看起来像这样:

let data = [
  {
    name: 'Peter',
    age: 26,
    sID: 546589995544
  },
  {
    name: 'John',
    age: 33,
    sID: 554589525469
  }
];

实际上还有很多,不过,这就是结构。

因此,如果 diff 库说,这就是更改:

let changes = {
  {
    age: 34,
    sID: 554589525469
  }
};

(注意我现在有一个对象的对象,而不是一个对象数组。这就是 diff-library returns)

我希望合并后的对象是

[
  {
    name: 'Peter',
    age: 26,
    sID: 546589995544
  },
  {
    name: 'John',
    age: 34,
    sID: 554589525469
  }
];

(约翰现在大了一岁)

所以我完全相信,如果我有一个对象的键作为标识符,这会容易得多,但我仍然认为必须有一个解决方案来解决这个问题。如您所见,sID 属性 可以充当标识符,它只是不是键。

如果有人能指出在这两种情况下如何做到这一点(有和没有对象的特定键),我将不胜感激

您可以使用 sId 映射进行快速查找:

const byId = new Map( data.map( el => [el.sID, el]));

然后对于每个更改,我们可以找到 obj 是否已经存在,如果不存在我们添加它,如果是我们变异:

changes.forEach(change => {
 const res = byId.get( change.sID );
 if( res ){
   Object.assign( res, change);
 }else{
   data.push(change);
   byId.set( change.sID, change);
 }
});

您可以使用 .find() 查找数组中应更改值的对象,Object.assign() 设置值

let data = [{
    name: 'Peter',
    age: 26,
    sID: 546589995544
  },
  {
    name: 'John',
    age: 33,
    sID: 554589525469
  }
];

let changes = [{
  age: 34,
  sID: 554589525469
}];

for (let prop of changes) {
  let {sID} = prop;
  Object.assign(data.find(({sID: id}) => id === sID), prop)
}

console.log(data);

使用lodash, you can accomplish this with unionBy

const newData = _.unionBy(changes, data, 'sID'); // values from changes will be picked

这将根据sID从两个数组中选取对象并将它们组合成一个数组。

如果你更改的数据是 object of objects ,你可以使用 Object.values 循环数据值并通过 Object.assign

合并相同的 id 数据
let data = [
  {
    name: 'Peter',
    age: 26,
    sID: 546589995544
  },
  {
    name: 'John',
    age: 33,
    sID: 554589525469
  }
];

let changes = {
    0:
  {
    age: 34,
    sID: 554589525469
  }
};

data.filter((idx,i)=>
    Object.values(changes).forEach((index)=>
        (index.sID == idx.sID) ? Object.assign(data[i],index) : null
        )
);
console.log(data);