Converting lodash _.uniqBy() to native javascript - javascript

Here in this snippet i am stuck as in _.uniqBy(array,iteratee),this
iteratee can be a function or a string at the same time
Where to put the condition to check uniqness on the property because itratee function can be anything
var sourceArray = [ { id: 1, name: 'bob' },
{ id: 1, name: 'bill' },
{ id: 1, name: 'bill' } ,
{id: 2,name: 'silly'},
{id: 2,name: 'billy'}]
function uniqBy (inputArray, callback) {
return inputArray.filter(callback)
}
var inputFunc = function (item) {
return item.name
}
// var destArray = _.uniqBy(sourceArray,'name')
var destArray = uniqBy(sourceArray, inputFunc)
console.log('destArray', destArray)
Any leads on this will be most appreciated.

An ES6 uniqBy using Map with a complexity of O(n):
const uniqBy = (arr, predicate) => {
const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
return [...arr.reduce((map, item) => {
const key = (item === null || item === undefined) ?
item : cb(item);
map.has(key) || map.set(key, item);
return map;
}, new Map()).values()];
};
const sourceArray = [
{ id: 1, name: 'bob' },
{ id: 1, name: 'bill' },
null,
{ id: 1, name: 'bill' } ,
{ id: 2,name: 'silly'},
{ id: 2,name: 'billy'},
null,
undefined
];
console.log('id string: ', uniqBy(sourceArray, 'id'));
console.log('name func: ', uniqBy(sourceArray, (o) => o.name));

Refactored #ori-drori's solution and removed
undefined
null
extra numbers in mixed array
return [] if first param is not Array
const uniqBy = (arr, predicate) => {
if (!Array.isArray(arr)) { return []; }
const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
const pickedObjects = arr
.filter(item => item)
.reduce((map, item) => {
const key = cb(item);
if (!key) { return map; }
return map.has(key) ? map : map.set(key, item);
}, new Map())
.values();
return [...pickedObjects];
};
const a = [
12,
undefined,
{ id: 1, name: 'bob' },
null,
{ id: 1, name: 'bill' },
null,
undefined
];
const b = [
12,
{ id: 1, name: 'bob' },
{ id: 1, name: 'bill' },
];
uniqBy(a, 'name');
uniqBy(b, Math.floor);
uniqBy([2.1, 1.2, 2.3], Math.floor);

I'm running my code through Webpack via CreateReactApp, it must be using a polyfill for spread that uses slice. Here's what I did instead, a variation of #oridori's answer:
const uniqBy = (arr: any[], predicate: (item: any) => string) => {
const cb = typeof predicate === 'function' ? predicate : (o) => o[predicate];
const result = [];
const map = new Map();
arr.forEach((item) => {
const key = (item === null || item === undefined) ? item : cb(item);
if (!map.has(key)) {
map.set(key, item);
result.push(item);
}
});
return result;
};

For those looking for the one line answer
var inputArr = [
{ id: 1, name: { first: 'bob' } },
{ id: 1, name: { first: 'bill' } },
{ id: 1, name: { first: 'bill' } },
{ id: 1 },
undefined,
{ id: 2, name: { first: 'silly' } },
{ id: 2, name: { first: 'billy' } }
]
var uniqBy = (arr, key) => {
return Object.values(arr.reverse().reduce((m, i) => {m[key.split('.').reduce((a, p) => a?.[p], i)] = i; return m;}, {}))
}
console.log(uniqBy(inputArr, 'id'))
console.log(uniqBy(inputArr, 'name.first'))

You could use a sort ordered by name and a filter based on the neighborhood comparison like this :
var sourceArray = [ { id: 1, name: 'bob' },
{ id: 1, name: 'bill' },
{ id: 1, name: 'bill' } ,
{id: 2,name: 'silly'},
{id: 2,name: 'billy'}]
var uniqBy = (inputArray, callback) => inputArray.sort((a,b) => callback(a) > callback(b))
.filter((x,i,arr) => i === arr.length -1 ? true : callback(x) !== callback(arr[i+1]));
var inputFunc = item => item.name;
var destArray = uniqBy(sourceArray, inputFunc)
console.log('destArray', destArray)

Related

get array of object value and nested array of object value

I've this nested array of object array:
const items = [
{
id: 1,
name: 'banana',
selected: true,
},
{
id: 2,
subItems: [
{
id: '2a',
name: 'apple',
selected: true,
},
{
id: '2b',
name: 'orange',
selected: false,
},
],
},
{
id: 3,
name: 'watermalon',
selected: true,
},
{
id: 4,
name: 'pear',
selected: false,
},
]
How can I get the ids base on selected property?
I manage to get the first level, I've tried
const selectedItemId = items.map(item => item.selected && item.id).filter(Boolean)
but how can I select the ids which is in the subItems? I expect the result to be [1, '2a', 3]
Flatten the array first. Be careful of using && item.id inside the mapper because that'll mean that falsey IDs (like 0, which is a reasonable starting number in some schemes) will be excluded.
const items=[{id:1,name:"banana",selected:!0},{id:2,subItems:[{id:"2a",name:"apple",selected:!0},{id:"2b",name:"orange",selected:!1}]},{id:3,name:"watermalon",selected:!0},{id:4,name:"pear",selected:!1}];
const output = items
.flatMap(item => [item].concat(item.subItems ?? []))
.filter(item => item.selected)
.map(item => item.id);
console.log(output);
You can recursively traverse all the items and select the items that have selected set to true.
const items = [
{ id: 1, name: "banana", selected: true },
{
id: 2,
subItems: [
{ id: "2a", name: "apple", selected: true },
{ id: "2b", name: "orange", selected: false },
],
},
{ id: 3, name: "watermalon", selected: true },
{ id: 4, name: "pear", selected: false },
];
function getSelectedItems(items, selectedItems = []) {
for (let item of items) {
if (item.subItems) {
getSelectedItems(item.subItems, selectedItems);
} else if (item.selected) {
selectedItems.push(item.id);
}
}
return selectedItems;
}
console.log(getSelectedItems(items));
let newArray = [];
items.forEach(i=>{
if(i.selected){
newArray.push(i.id)
}
if(i.subItems){
i.subItems.forEach(j=>{
if(j.selected){
newArray.push(j.id)
}
})
}
});
so this is bit lengthy. with 2 map loops
You can do:
const items=[{id:1,name:"banana",selected:!0},{id:2,subItems:[{id:"2a",name:"apple",selected:!0},{id:"2b",name:"orange",selected:!1}]},{id:3,name:"watermalon",selected:!0},{id:4,name:"pear",selected:!1}]
const output = items
.reduce((a, c) => [...a, c, ...(c.subItems || [])], [])
.filter(o => o.selected)
.map(({ id }) => id)
console.log(output)
Checking if a subItems array exsist in the item and recusively calling a function to extract selected Items will solve the issue.
function extractSubItems (items){
var selectItemsId = [];
selectItemsId = selectItemsId + items.map(item => {
if (item.selected===true){
return item.id;
}
if (item.subItems){
return extractSubItems(item.subItems);
}
}).filter(Boolean);
return selectItemsId
}
You can use Array#reduce in a nested fashion as follows:
const items = [ { id: 1, name: 'banana', selected: true, }, { id: 2, subItems: [ { id: '2a', name: 'apple', selected: true, }, { id: '2b', name: 'orange', selected: false, }, ], }, { id: 3, name: 'watermalon', selected: true, }, { id: 4, name: 'pear', selected: false, }, ],
output = items
.reduce(
(prev, {id,selected,subItems}) =>
subItems ?
selected ?
[...prev,id,...subItems.reduce( (p, {id:ID,selected:SEL}) => SEL ? [...p,ID] : p, [] )] :
[...prev,...subItems.reduce( (p, {id:ID,selected:SEL}) => SEL ? [...p,ID] : p, [] )] :
selected ?
[...prev,id] :
prev, []
);
console.log( output )
1 - Loop through items array
2 - if there is no subItems array then find the id of the item using condition
3 - if there is a subItems array then loop through that and find the id using condition
const result = []
items.map(item=>{
item.subItems ?
item.subItems.map(sub=>{
sub.selected && result.push(sub.id)
})
: item.selected && result.push(item.id)
})
console.log(result) // [1, "2a", 3]
This also works:
var ids = [
... items.filter(
it => it.selected || (it.subItems && it.subItems.some( sub => sub.selected ))
)
.map( it =>
it.subItems
? it.subItems.filter( it_sub => it_sub.selected ).map( it_sub => it_sub.id )
: [it.id]
)
].flat()
With resursive of subItems :
const items=[
{id:1,name:"banana",selected:!0},
{id:2,subItems:
[
{id:"2a",name:"apple",selected:!0},
{id:"2b",name:"orange",selected:!1},
{id:"2c",subItems:
[
{id:"2c1",name:"apple1",selected:!0},
{id:"2c1",name:"orange1",selected:!1}
]
},
]
},
{id:3,name:"watermalon",selected:!0},
{id:4,name:"pear",selected:!1}
];
const getSubItem = (obj) => {
let result = !obj.hasOwnProperty('subItems') ? [obj] : obj.subItems.reduce((res, item) => {
return res.concat(getSubItem(item))
}, [])
return result.filter(item => item.selected)
}
const result = items.reduce((res, item) => {
let subItem = getSubItem(item)
return res.concat(getSubItem(item))
}, [])
console.log(result)

How to change the nested array object to object depending on type in javascript

I would like to know how to change nested array object to object depending on key in javascript
I have objects obj1 and obj2, depending on key item type change the object.
function changeObj(obj){
let result = obj.reduce(function (acc, item) {
if(item.items.trim() !== "" && item.key.trim() !== ""){
acc[item.key] = item.items
return acc
}
return acc
}, {});
return result;
}
let result = this.changeObj(obj2)
var obj1 = [
{ id:0, items:["SG","AU"], count: 2, key:"countries"},
{ id:1, items:["finance"], count: 3 key:"info"}
]
var obj2 = [
{ id:0, items: "SG", key: "country"},
{ id:1, items: "details", key: "info"}
]
Expected Output:
// if items key is array
{
fields: {
countries: ["SG","AU",2],
info: ["finance",3]
}
}
//if items key is string
{
fields: {
country: "SG",
info: "details"
}
}
I think the reason your code is not running is because the wrong format of your objects (1 and 2). Your code is okay except the condition because trim() only works on string type so it errors on array. Try this code snippet
function changeObj(obj){
let result = obj.reduce(function (acc, item) {
acc[item.key] = item.items;
return acc;
}, {});
return result;
}
var obj1 = [
{ id:0, items:["SG","AU"], count: 2, key:"countries"},
{ id:1, items:["finance"], count: 3, key:"info"}
]
var obj2 = [
{ id:0, items: "SG", key: "country"},
{ id:1, items: "details", key: "info"}
]
console.log(changeObj(obj1));
const changeObj = obj =>
obj.reduce((acc, item) => {
if (Array.isArray(item.items)) {
acc[item.key] = [...item.items, item.count];
} else {
acc[item.key] = item.items;
}
return acc;
}, {});
var obj1 = [
{ id: 0, items: ['SG', 'AU'], count: 2, key: 'countries' },
{ id: 1, items: ['finance'], count: 3, key: 'info' }
];
var obj2 = [
{ id: 0, items: 'SG', key: 'country' },
{ id: 1, items: 'details', key: 'info' }
];
console.log(changeObj(obj1));
console.log(changeObj(obj2));
or cleaned up even more
const changeObj = obj =>
obj.reduce((acc, { items, key, count }) => {
Array.isArray(items) ? (acc[key] = [...items, count]) : (acc[key] = items);
return acc;
}, {});
var obj1 = [
{ id: 0, items: ['SG', 'AU'], count: 2, key: 'countries' },
{ id: 1, items: ['finance'], count: 3, key: 'info' }
];
var obj2 = [
{ id: 0, items: 'SG', key: 'country' },
{ id: 1, items: 'details', key: 'info' }
];
console.log(changeObj(obj1));
console.log(changeObj(obj2));

Get list of duplicate objects in an array of objects

I am trying to get duplicate objects within an array of objects. Let's say the object is like below.
values = [
{ id: 10, name: 'someName1' },
{ id: 10, name: 'someName2' },
{ id: 11, name: 'someName3' },
{ id: 12, name: 'someName4' }
];
Duplicate objects should return like below:
duplicate = [
{ id: 10, name: 'someName1' },
{ id: 10, name: 'someName2' }
];
You can use Array#reduce to make a counter lookup table based on the id key, then use Array#filter to remove any items that appeared only once in the lookup table. Time complexity is O(n).
const values = [{id: 10, name: 'someName1'}, {id: 10, name: 'someName2'}, {id: 11, name:'someName3'}, {id: 12, name: 'someName4'}];
const lookup = values.reduce((a, e) => {
a[e.id] = ++a[e.id] || 0;
return a;
}, {});
console.log(values.filter(e => lookup[e.id]));
Let's say you have:
arr = [
{ id:10, name: 'someName1' },
{ id:10, name: 'someName2' },
{ id:11, name: 'someName3' },
{ id:12, name: 'someName4' }
]
So, to get unique items:
unique = arr
.map(e => e['id'])
.map((e, i, final) => final.indexOf(e) === i && i)
.filter(obj=> arr[obj])
.map(e => arr[e]);
Then, result will be
unique = [
{ id:10, name: 'someName1' },
{ id:11, name: 'someName3' },
{ id:12, name: 'someName4' }
]
And, to get duplicate ids:
duplicateIds = arr
.map(e => e['id'])
.map((e, i, final) => final.indexOf(e) !== i && i)
.filter(obj=> arr[obj])
.map(e => arr[e]["id"])
List of IDs will be
duplicateIds = [10]
Thus, to get duplicates objects:
duplicate = arr.filter(obj=> dublicateIds.includes(obj.id));
Now you have it:
duplicate = [
{ id:10, name: 'someName1' },
{ id:10, name: 'someName2' }
]
Thanks https://reactgo.com/removeduplicateobjects/
You haven't clarified whether two objects with different ids, but the same "name" count as a duplicate. I will assume those do not count as a duplicate; in other words, only objects with the same id will count as duplicate.
let ids = {};
let dups = [];
values.forEach((val)=> {
if (ids[val.id]) {
// we have already found this same id
dups.push(val)
} else {
ids[val.id] = true;
}
})
return dups;
With lodash you can solve this with filter and countBy for complexity of O(n):
const data = [{ id: 10,name: 'someName1' }, { id: 10,name: 'someName2' }, { id: 11,name: 'someName3' }, { id: 12,name: 'someName4' } ]
const counts = _.countBy(data, 'id')
console.log(_.filter(data, x => counts[x.id] > 1))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
You could do the same with ES6 like so:
const data = [{ id: 10,name: 'someName1' }, { id: 10,name: 'someName2' }, { id: 11,name: 'someName3' }, { id: 12,name: 'someName4' } ]
const countBy = (d, id) => d.reduce((r,{id},i,a) => (r[id] = a.filter(x => x.id == id).length, r),{})
const counts = countBy(data, 'id')
console.log(data.filter(x => [x.id] > 1))
You can use an array to store unique elements and use filter on values to only return duplicates.
const unique = []
const duplicates = values.filter(o => {
if(unique.find(i => i.id === o.id && i.name === o.name)) {
return true
}
unique.push(o)
return false;
})
With lodash you can use _.groupBy() to group elements by their id. Than _.filter() out groups that have less than two members, and _.flatten() the results:
const values = [{id: 10, name: 'someName1'}, {id: 10, name: 'someName2'}, {id: 11, name:'someName3'}, {id: 12, name: 'someName4'}];
const result = _.flow([
arr => _.groupBy(arr, 'id'), // group elements by id
g => _.filter(g, o => o.length > 1), // remove groups that have less than two members
_.flatten // flatten the results to a single array
])(values);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
An alternative based in #ggorlen solution with new Map() as accumulator (for better performance) and without unary operator ++ (not advised by default in projects with ESLint).
const values = [{ id: 10, name: "someName1" }, { id: 10, name: "someName2" }, { id: 11, name: "someName3" }, { id: 12, name: "someName4" },];
const lookup = values.reduce((a, e) => {
a.set(e.id, (a.get(e.id) ?? 0) + 1);
return a;
}, new Map());
console.log(values.filter(e => lookup.get(e.id) > 1));
Try this
function checkDuplicateInObject(propertyName, inputArray) {
var seenDuplicate = false,
testObject = {};
inputArray.map(function(item) {
var itemPropertyName = item[propertyName];
if (itemPropertyName in testObject) {
testObject[itemPropertyName].duplicate = true;
item.duplicate = true;
seenDuplicate = true;
}
else {
testObject[itemPropertyName] = item;
delete item.duplicate;
}
});
return seenDuplicate;
}
referred from : http://www.competa.com/blog/lets-find-duplicate-property-values-in-an-array-of-objects-in-javascript/

Updating selection of array's values

I have two arrays. Each array could have a different number of objects but they each have the same properties but could have different values. For example
var Array1 = [ { id: '1', value: a },
{ id: '2', value: b } ]
var Array2 = [ { id: '', value: c },
{ id: '', value: d },
{ id: '', value: a } ]
What I want
AfterArray = [ { id: '1', value: a },
{ id: '3', value: c },
{ id: '4', value: d } ]
What's happening is that array1's object will be removed if it doesn't have array2's value. If it does have array2's value, it will keep the original id. If an object is in array2 that isn't in array1, an id will be generated (UUID).
I'm assuming it might go something like this
afterArray = []
this.Array1.forEach((res, i) => {
this.Array2.forEach((res2, 2) => {
if(res.value == res2.value){
afterArray = afterArray.concat(this.Array1[i])
}
else {
// do something if values are not present then add to array.
// if added, add id to those empty properties.
}
})
})
Thanks!
You just need a simple mapping over Array2 with a find inside it, to find the matching value in Array1 if it exists:
const array1 = [
{
id: '1',
value: 'a'
},
{
id: '2',
value: 'b'
}
];
const array2 = [
{
id: '',
value: 'c'
},
{
id: '',
value: 'd'
},
{
id: '',
value: 'a'
}
];
const generateId = (() => {
// example generator function, use your own instead
let possibleIds = ['3', '4'];
let i = -1;
return () => {
i++;
return possibleIds[i];
};
})();
const result = array2.map(({ id, value }) => {
// find a matching value in array1 to merge the id:
const foundArr1Item = array1.find(({ value: ar1Val }) => ar1Val === value);
// otherwise, generate a new ID:
if (foundArr1Item) return { value, id: foundArr1Item.id };
return { value, id: generateId() };
});
console.log(result);
If I understood it right, this should do your job:
(find the comments in the code)
Array1 = [
{
id: '1',
value: "a"
},
{
id: '2',
value: "b"
}
]
Array2 = [
{
id: '',
value: "c"
},
{
id: '',
value: "d"
},
{
id: '',
value: "a"
}
]
// keep Array1's objects if it has a value matching a value from any Array2 object
// Also remove those objects from Array2
newArray1 = Array1.reduce((acc, elem) => {
let indexOfObInArray2 = Array2.findIndex(eachArray2Elem => {
return elem.value == eachArray2Elem.value
});
if (indexOfObInArray2 > -1) {
acc.push(elem);
Array2.splice(indexOfObInArray2, 1);
}
return acc;
}, [])
// Array of ids already taken by Objects from Array2, if they are non empty
idsTakenInArray2 = Array2.reduce((acc, x) => {
if (x.id != "") {
acc.push(x.id);
}
return acc;
}, []);
// random number to give ids
randomId = 1;
Array2 = Array2.map(eachElem => {
if (eachElem.id == '') {
while (Array1.find(eachArray1Elem => {
return eachArray1Elem.id == randomId
}) || idsTakenInArray2.indexOf(randomId) !== -1) {
randomId++;
}
eachElem.id = randomId;
idsTakenInArray2.push(randomId);;
}
return eachElem;
})
console.log(newArray1.concat(Array2));
check this, here is the code online https://stackblitz.com/edit/angular-zhzuqk , check your console you will see what you want to have as result
formtarrays(array1,array2) {
let ar = array1.concat(array2);
// delete items that exist in array1 but not in array2
ar = ar.filter((elem) => {
return !(array1.findIndex(item => item.value === elem.value) !== -1 && array2.findIndex(item => item.value === elem.value) === -1)
})
// get distinct values
const idList = [];
const distinct = [];
ar.forEach((item, index) => {
if (item !== undefined) {
idList['id'] = item.value;
if (idList.indexOf(item.value) < 0) {
if(item.id === '') {
item.id = (index + array1.length).toString();
}
distinct.push(item);
idList.push(item.value);
}
}
})
console.log(distinct);
return distinct;
}

What is the most efficient way to determine if a collection of objects has changed?

I've previously fetched a collection from the backend. I'm polling the backend for changes and have received another collection. The dataset is reasonable sized, so we don't need any optimizations... just fetched the whole thing again.
Running both datasets through algorithm f(previousCollection, newCollection), I would like to generate results for added, removed, and modified.
What is the most efficient way to do this? Or, better put, how do you all do this in your day to day work?
Example data:
old:
{id: 1, foo: 'bar'},
{id: 2, foo: 'bar'}
new:
{id: 2, foo: 'quux'},
{id: 4, foo: 'bar'}
expected result:
{event: 'removed', id: 1},
{event: 'modified', id: 2},
{event: 'added', id: 4}
Using Array#reduce and Array#find makes this quite simple
function f(prev, curr) {
var result = prev.reduce(function(result, p) {
var c = curr.find(function(item) {
return item.id == p.id;
});
if(c) {
if(c.foo !== p.foo) {
result.push({event: 'modified', id:p.id});
}
} else {
result.push({event: 'removed', id:p.id});
}
return result;
}, []);
return curr.reduce(function(result, c) {
var p = prev.find(function(item) {
return item.id == c.id;
});
if(!p) {
result.push({event: 'added', id:c.id});
}
return result;
}, result);
}
var old = [
{id: 1, foo: 'bar'},
{id: 2, foo: 'bar'}
];
var curr = [
{id: 2, foo: 'quux'},
{id: 4, foo: 'bar'}
];
console.log(f(old, curr));
Just for laughs, this example is written in ES2015+ using Arrow functions, object shorthand and object de-structuring
var f = (previousCollection, newCollection) => newCollection.reduce((result, {id}) => {
if (!previousCollection.find(item => item.id == id)) {
result.push({event: 'added', id});
}
return result;
}, previousCollection.reduce((result, {id, foo}) => {
var {foo:newValue} = newCollection.find(item => item.id == id) || {};
if (newValue) {
if(newValue !== foo) {
result.push({event: 'modified', id});
}
} else {
result.push({event: 'removed', id});
}
return result;
}, []));
var old = [
{id: 1, foo: 'bar'},
{id: 2, foo: 'bar'}
];
var curr = [
{id: 2, foo: 'quux'},
{id: 4, foo: 'bar'}
];
console.log(f(old, curr));
This is more of a comprehensive comparison.
Possible Changes:
Value of a property updated
A new property added
A property deleted. This can overlap value changed as value is different
An object is deleted.
A new object is added.
/*
Status:
Key Added,
Key Deleted,
Object Added,
Object Deleted,
Modified,
Has Duplicate
*/
function getUpdates(old, newState) {
var result = [];
// Create new copies
old = old.slice(0);
newState = newState.slice(0);
// Deleted Objects
mismatchingObjects(old, newState, result)
old.forEach(function(o) {
var report = {};
report.id = o.id;
var match = newState.filter(function(item) {
return item.id === o.id
});
var mlen = match.length;
if (mlen) {
if(mlen === 1 && stringMatch(o, match[0])) return
if(mlen > 1) report.hasDuplicate = true;
match.forEach(function(m, index) {
if (stringMatch(o, m)) return
keyMatches(o, m, index, report)
matchValue(o, m, index, report)
})
}
if(Object.keys(report).length > 1)
result.push(report)
});
return result
}
function stringMatch(o1, o2) {
return JSON.stringify(o1) === JSON.stringify(o2);
}
function keyMatches(o1, o2, index, report) {
var k1 = Object.keys(o1);
var k2 = Object.keys(o2);
if (k1.join() !== k2.join()) {
report.keysRemoved = (report.keysRemoved || [])
var r = k1.filter(function(k) {
return k2.indexOf(k) < 0;
});
report.keysRemoved.push({
keys: r,
objectIndex: index
});
report.keysAdded = (report.keysAdded || [])
var a = k2.filter(function(k) {
return k1.indexOf(k) < 0;
});
report.keysAdded.push({
keys: a,
objectIndex: index
})
}
}
function matchValue(o1, o2, index, report) {
report.keysChanged = report.keysChanged || [];
var keys = [];
for (var k in o1) {
if (o1[k] !== o2[k] && o2[k]) {
keys.push(k);
}
}
report.keysChanged.push({
keys: keys,
objectIndex: index
})
}
function mismatchingObjects(o1, o2, result) {
var ids1 = o1.map(function(o) {
return o.id
});
var ids2 = o2.map(function(o) {
return o.id
});
ids1.forEach(function(id) {
if (ids2.indexOf(id) < 0)
result.push({
id: id,
status: "Object Deleted"
})
})
ids2.forEach(function(id) {
if (ids1.indexOf(id) < 0)
result.push({
id: id,
status: "Object Added"
})
})
}
var old = [{
id: 1,
foo: 'bar'
}, {
id: 2,
foo: 'bar'
}, {
id: 3,
foo: "test",
deletedKey: "bla bla"
}]
var newState = [{
id: 2,
foo: 'quux'
}, {
id: 3,
foo: "test",
addedKey: "bla bla"
}, {
id: 3,
foo: "test2"
}, {
id: 4,
foo: 'bar'
}];
console.log(getUpdates(old, newState))
Note: This may seems a bit of an overkill. If you feel so, please accept my apologies.

Categories

Resources