Is there a way to return the difference between two arrays in JavaScript? I can not use indexOf in this case.
For example:
var a1 = [{"a":"A"},{"b":"B"}];
var a2 = [{"a":"A"},{"b":"B"},{"c":"C"}];
// need [{"c":"C"}]
Please advise.
Is there a way to return the difference between two arrays in JavaScript? I can not use indexOf in this case.
For example:
var a1 = [{"a":"A"},{"b":"B"}];
var a2 = [{"a":"A"},{"b":"B"},{"c":"C"}];
// need [{"c":"C"}]
Please advise.
One object can never be the same as another object even if they have the same content. They would still be different instances of Objects.
That means you have to compare keys and values to check that they match, or in this case, don't match.
var a1 = [{"a":"A"},{"b":"B"}];
var a2 = [{"a":"A"},{"b":"B"},{"c":"C"}];
var a3 = a2.filter(function(o) {
return Object.keys(o).some(function(k) {
return a1.every(function(o2) {
return !(k in o2) || (o2[k] != o[k]);
});
});
});
As I mentioned in my comment, objects are only equal if they refer to the same instance. Therefore, any built-in system will not do, least of all == and ===. So, first you must define your own comparison function.
Let's say that two objects are equal if they contain the same keys with the same values.
function areObjectsEqual(a,b) {
function helper(a,b) {
var k;
for( k in a) {
if( a.hasOwnProperty(k)) {
if( !b.hasOwnProperty(k)) return false;
if( typeof a[k] != typeof b[k]) return false;
if( typeof a[k] == "object") {
if( !areObjectsEqual(a[k],b[k])) return false;
// the above line allows handling of nested objects
}
else {
if( a[k] != b[k]) return false;
// this comparison is technically strict
// because we already checked typeof earlier
}
}
}
}
return helper(a,b) && helper(b,a);
}
Okay, now that that's out of the way, we can compare our functions.
function array_diff(a,b) {
var result = [], l = a.length, i, m = b.length, j;
outer:
for( i=0; i<l; i++) {
for( j=0; j<m; j++) {
if( typeof a[i] != typeof b[j]) continue;
if( typeof a[i] == "object") {
if( !areObjectsEqual(a[i],b[j])) continue;
}
else {
if( a[i] != b[j]) continue;
}
// if we got to here, it's a match!
// ... so actually we want to skip over the result :p
continue outer;
}
// okay, if we get HERE then there was no match,
// because we skipped the "continue outer"
result.push(a[i]);
}
return result;
}
And there you go!
array_diff check of areObjectsEqualresult at the end of array_diff, although that doesn't give me the correct answer either.a that are not in b.array_diff, makes for a nasty read. Other than that, GJ! :)=== is not good when used on objects. So I check for type first, obviously we can reject if they're different. If the type is the same, then handle comparison differently based on if that type is object or not.Easy and simple way to achieve your goal
var a1 = [{"a":"A"},{"b":"B"}];
var a2 = [{"a":"A"},{"c":"C"},{"b":"B"}];
var max = (a1.length > a2.length) ? a1 : a2;
var min = (a1.length > a2.length) ? a2 : a1;
var newArray = [];
for ( var i = 0; i < max.length; i++ ) { // saving elements into string
max[i] = JSON.stringify(max[i]);
if ( typeof min[i] !== undefined ) {
min[i] = JSON.stringify(min[i]);
}
}
for ( var i = 0; i < max.length; i++ ) { // checking values uniqueness
if ( min.indexOf(max[i]) === -1 ) {
newArray.push(max[i]);
}
}
// if you need new Array's elements back in object do following iteration
for ( var i in newArray ) { // loop recreate results array's elements into object again
newArray[i] = JSON.parse(newArray[i]);
}
console.log(newArray); // result : [Object { c="C"}]
max and min variables, if some indices are missing it doesn't matter because max will hold array which has more elements in it even if there anything is missingvar a1 = [{"a":"A"},{"b":"B"}];
var a2 = [{"a":"A"},{"b":"B"},{"c":"C"}];
var obj = {}, result = [];
function updateObjectCount(currentItem) {
var keys, key;
for (key in currentItem) {
if (currentItem.hasOwnProperty(key)) {
keys = key;
break;
}
}
obj[key] = obj[key] || {};
obj[key][currentItem[key]] = (obj[key][currentItem[key]] || 0) + 1;
}
a1.forEach(updateObjectCount);
a2.forEach(updateObjectCount);
for (var key1 in obj) {
if (obj.hasOwnProperty((key1))) {
for (var key2 in obj[key1]) {
if (obj.hasOwnProperty((key1))) {
if (obj[key1][key2] === 1) {
var temp = {};
temp[key1] = key2;
result.push(temp)
}
}
}
}
}
console.log(result);
# [ { c: 'C' } ]