Поэтому у меня есть такой сценарий, когда у меня есть клиент-приложение, которое отправляет данные (массив объектов) на сервер, который затем пересылает данные другим клиентам, подключенным к этому серверу.
В клиенте-приложении данные постоянно меняются, что означает: изменение значений, появление новых объектов внутри массива, удаление объектов и т.д....
Теперь я хочу, чтобы другие клиенты всегда получали последние данные. И поскольку я не хочу, чтобы клиент-приложение просто выталкивало все новые данные на сервер, а затем пересылало все новые данные другим клиентам, я решил разрешить клиенту-приложению изменять эти изменения (используя эту библиотеку: https://www.npmjs.com/package/deep-object-diff).
Затем другие клиенты получают массив объектов только с данными, которые фактически изменились, и поскольку они знают предыдущий массив данных, я хочу, чтобы они "объединили" массив изменений со старым объектом данных.
Моя реальная проблема - это слияние. Я не знаю, как правильно это сделать. Особенно, если у меня есть массив объектов без ключа для объектов.
Поэтому мои данные выглядят примерно так:
let data = [
{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 33,
sID: 554589525469
}
];
На самом деле там гораздо больше, но хорошо, вот и структура.
Поэтому, если библиотека diff написана, это изменения:
let changes = {
{
age: 34,
sID: 554589525469
}
};
(обратите внимание, что теперь у меня есть объект объектов, а не массив объектов. То, что возвращает библиотека diff-library)
Я хочу, чтобы объединенный объект был
[
{
name: 'Peter',
age: 26,
sID: 546589995544
},
{
name: 'John',
age: 34,
sID: 554589525469
}
];
(Джон сейчас на год старше)
Поэтому я полностью верю, что это было бы намного проще, если бы у меня был ключ к объектам в качестве идентификатора, но все же я думаю, что для такого сценария должно быть решение. И, как вы можете видеть, свойство sID может действовать как идентификатор, а его просто не ключ.
Если бы кто-то мог указать, как это сделать в обоих случаях (с конкретным ключом для объектов и без него)
Вы можете использовать .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);
Object.values()
или Object.entries()
для преобразования объекта в массив массивов свойств, пар значений. Почему вы не включили фактический объект, используемый в коде в вопросе?
Если ваши данные изменений являются object of objects
, вы можете использовать Object.values
для циклического значения данных и слияния одинаковых идентификационных данных с помощью Object.assign
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);
Object.keys
, это будет получать ключи объекта в виде списка массивов ..
Используя lodash, вы можете выполнить это с помощью unionBy:
const newData = _.unionBy(changes, data, 'sID'); // values from changes will be picked
Это позволит выбрать объекты из массивов на основе sID
и объединить их в один массив.
Вы можете использовать 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);
}
});