Skip to content

Instantly share code, notes, and snippets.

@Dan6erbond
Last active August 31, 2020 17:05
Show Gist options
  • Save Dan6erbond/ab6305669db07927eb564e286d8d34aa to your computer and use it in GitHub Desktop.
Save Dan6erbond/ab6305669db07927eb564e286d8d34aa to your computer and use it in GitHub Desktop.
A TypeScript array merger that reads updates from last known store state, updated local state and updated remote state.
function mergeArrays<T>(
oldCollection: T[],
updatedCollection: T[],
remoteCollection: T[],
uniqueIdentifier: (item: T) => string | number
) {
const oldIds = oldCollection.map((i) => uniqueIdentifier(i));
const updatedIds = updatedCollection.map((i) => uniqueIdentifier(i));
const remoteIds = remoteCollection.map((i) => uniqueIdentifier(i));
const remoteRemovals = oldIds.filter((i) => !remoteIds.includes(i));
const localUpdates = updatedCollection
.filter((i) => {
const id = uniqueIdentifier(i);
const oldItem = oldCollection.find((_i) => {
const _id = uniqueIdentifier(i);
return _id === id;
});
if (oldItem) {
for (let attr of Object.keys(oldItem).concat(Object.keys(i))) {
if ((i as any)[attr] !== (oldItem as any)[attr]) {
return true;
}
}
}
return false;
})
.map((i) => uniqueIdentifier(i));
// console.log(localUpdates);
const resultCollection = updatedCollection
.filter(
(i) =>
localUpdates.includes(uniqueIdentifier(i)) ||
!remoteRemovals.includes(uniqueIdentifier(i)) ||
!(
localUpdates.includes(uniqueIdentifier(i)) &&
remoteRemovals.includes(uniqueIdentifier(i))
)
)
.map((i) => {
const id = uniqueIdentifier(i);
const oldItem =
oldCollection.find((_i) => {
const _id = uniqueIdentifier(i);
return _id === id;
}) || {};
// console.log(oldItem);
const remoteItem =
remoteCollection.find((_i) => {
const _id = uniqueIdentifier(i);
return _id === id;
}) || {};
// console.log(remoteItem);
const merge = (obj1: any, obj2: any, obj3: any) => {
const returnObj = {
...obj3,
...obj2,
...obj1,
};
// console.log(obj1, obj2, obj3);
for (let attr of Object.keys(returnObj)) {
// console.log(obj2[attr] !== returnObj[attr] ? obj2[attr] : obj3[attr]);
returnObj[attr] =
obj2[attr] !== obj1[attr]
? obj2[attr]
: obj3[attr] !== undefined
? obj3[attr]
: obj1[attr];
}
// console.log(returnObj);
return returnObj;
};
return merge(oldItem, i, remoteItem);
});
resultCollection.push(
...remoteCollection.filter((i) => {
const id = uniqueIdentifier(i);
/* console.log(
!(oldIds.includes(id) && !updatedIds.includes(id)) && // wasn't removed locally
!updatedIds.includes(id) // was already added to list
); */
return (
!(oldIds.includes(id) && !updatedIds.includes(id)) &&
!updatedIds.includes(id)
);
})
);
return resultCollection;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment