Skip to content

Instantly share code, notes, and snippets.

@ratulSharker
Last active January 24, 2020 18:47
Show Gist options
  • Save ratulSharker/44798d1d59d6c729030fa3f24da4b2ca to your computer and use it in GitHub Desktop.
Save ratulSharker/44798d1d59d6c729030fa3f24da4b2ca to your computer and use it in GitHub Desktop.
JS Data model difference calculator.
// Base model
function BaseModel() {
}
BaseModel.prototype.difference = function(latestModel, arrDiffActual = false) {
const difference = {};
const self = this;
Object.keys(this).forEach( function(key) {
if(self[key] instanceof BaseModel) {
// kind of another base model
const keyValueDifference = self[key].difference(latestModel[key]);
if(Object.keys(keyValueDifference).length > 0) {
difference[key] = keyValueDifference;
}
} else if(Array.isArray(self[key])) {
// item is type of array
const diffArr = self.arrDifference(self[key], latestModel[key], arrDiffActual);
if(diffArr !== null) {
difference[key] = diffArr;
}
}
else {
// basic type
if(self[key] !== latestModel[key]) {
difference[key] = latestModel[key];
}
}
});
return difference;
}
// Array items supported features.
// 1. Supports heterogenus array.
// 2. Array of different length is considered different.
// 3. If array item is placed at different position, it can be considered two ways
// 3.1 The whole array is changed.
// 3.2 Only those items are changed, where item do not match at specified position.
// the behaviour in #3 can be controlled using `actualDiff`.
BaseModel.prototype.arrDifference = function(origArr, newArr, actualDiff) {
if(origArr.length !== newArr.length) {
return newArr;
} else {
// now loop through each array element
const diffArr = []
for(let index = 0; index < origArr.length; index++) {
if(origArr[index] instanceof BaseModel) {
// item is type of base model
const keyValueDifference = origArr[index].difference(newArr[index]);
if(Object.keys(keyValueDifference).length > 0) {
diffArr.push(keyValueDifference);
}
} else if(Array.isArray(origArr[index])) {
// item is type of array
const difference = this.arrDifference(origArr[index], newArr[index], actualDiff);
if(difference !== null) {
diffArr.push(difference);
}
} else {
// basic type
if(origArr[index] !== newArr[index]) {
diffArr.push(newArr[index]);
}
}
}
if(actualDiff) {
return diffArr.length > 0 ? diffArr : null;
} else {
return diffArr.length > 0 ? newArr : null;
}
}
}
// Submodel user
function User (firstname, lastname, status, devices) {
BaseModel.call(this);
this.firstname = firstname;
this.lastname = lastname;
this.status = status;
this.devices = devices;
}
User.prototype = BaseModel.prototype;
// Submodel user status
function UserStatus (id, name) {
BaseModel.call(this);
this.id = id;
this.name = name;
}
UserStatus.prototype = BaseModel.prototype;
// Submodel device
function Device(id, type, name) {
BaseModel.call(this);
this.id = id;
this.type = type;
this.name = name;
}
Device.prototype = BaseModel.prototype;
const iPhone5 = new Device(1, "mobile", "iphone 5");
const macbook = new Device(2, "laptop", "Macbook pro 2015");
const smartwatch = new Device(3, "smartwatch", "Smartwatch 3");
const ratul = new User("Ratul", "sharker", new UserStatus(1, "ACTIVE"), [iPhone5, macbook]);
const ratulChanged = new User("Ratul", "dorker", new UserStatus(2, "INACTIVE"), [iPhone5, smartwatch]);
console.log(ratul.difference(ratulChanged, false));
function MultiLevelArrModel(arr) {
BaseModel.call(this);
this.arr = arr;
}
MultiLevelArrModel.prototype = BaseModel.prototype;
const mLvlArr = new MultiLevelArrModel([[1, 2, 3], [3, 4]]);
const mLvlArrChanged = new MultiLevelArrModel([[1, 2, 3], [4, 3]]);
console.log(mLvlArr.difference(mLvlArrChanged, true));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment