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

时间:2017-10-19 13:57:36

标签: javascript arrays merge javascript-objects array-difference

所以我有这种情况,我有一个 client-app ,它将数据(对象数组)发送到服务器,然后将数据转发给其他客户端已连接到此服务器。

client-app 中,数据不断变化,这意味着:值会更改,阵列中的新对象会弹出,对象会被删除,等等......

现在我希望其他客户始终接收最新数据。因为我不希望 client-app 只将全新数据推送到服务器,然后将全新数据转发给< strong>其他客户,我决定让客户端应用仅推送更改(使用此库:https://www.npmjs.com/package/deep-object-diff)。

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

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

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

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

实际上还有更多但很好,就是结构。

因此,如果差异库说,这是变化:

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

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

我希望合并的对象是

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

(约翰现在大一岁)

所以我完全相信,如果我将对象的密钥作为标识符,这会更容易,但我认为必须有一个完全符合这种情况的解决方案。正如您所看到的, sID 属性可以充当标识符,它只是一个密钥。

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

4 个答案:

答案 0 :(得分:1)

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

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);
 }
});

答案 1 :(得分:1)

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

&#13;
&#13;
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);
&#13;
&#13;
&#13;

答案 2 :(得分:1)

使用lodash,您可以使用unionBy完成此操作:

Together with the Rank count in your select query, select unique id for each row, with the help of unique_id for each row only we will be able to update the exact row in the table. Please modify the column names matching to your table declaration

String sql1 = SELECT COUNT(DISTINCT s2.Total) AS Rank from class1 s1 
JOIN class1 s2 on (s1.Total<=s2.Total)
GROUP BY s1.ID order by s1.Name ASC;

pst = conn.prepareStatement(sql1);
rs = pst.executeQuery();

String sql = "";
while (rs.next()) { 
    String sql = "update class1 set Position ='"+rs.getString(2)+"'"+"WHERE unique_id="+rs.getString(1);
    pst = conn.prepareStatement(sql);
    pst.execute();
}

这将从基于const newData = _.unionBy(changes, data, 'sID'); // values from changes will be picked 的两个数组中选择对象,并将它们组合成一个数组。

答案 3 :(得分:1)

如果您的更改数据为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);