The first thing you need is a way to compare two people for mathematical equivalence . We cannot use the === operator because it tests two objects for equivalence of identity, and not for mathematical equivalence. For instance:
var john = {name: "John Smith", age: 23}; var john2 = {name: "John Smith", age: 23}; console.log(john === john2);
Therefore, we create a function to compare two people:
console.log(similarPeople(john, john2)); function similarPeople(a, b) { return a.name === b.name && a.age === b.age; }
The reason the function is called similarPeople and not the samePeople is because two different people can have the same name and can be of the same age.
The difference of two sets A and B is defined as the set of all those elements from A that are not in B.
In the worst case, calculating the difference of two sets, A and B, sizes m and n would correspond to time O(m * n) . Not very effective:
function difference(a, b, eq) { if (arguments.length < 3) eq = function (a, b) { return a === b; }; var m = a.length; var n = b.length; var c = []; loop: for (var i = 0; i < m; i++) { var x = a[i]; for (var j = 0; j < n; j++) if (eq(b[j], x)) continue loop; c.push(x); } return c; }
Now you can separate the two lists of people as follows:
var people = [john, mary, bob]; var people2 = [john2]; console.log(difference(people, people2, similarPeople));
See the demo: http://jsfiddle.net/F7RDs/
Fortunately, there is a faster way to calculate the difference of sets for large sets: indices. Let me create a function to create an index of a list of people:
function indexFrom(people) { var length = people.length, index = {}; for (var i = 0; i < length; i++) { var person = people[i]; var name = person.name; if (index.hasOwnProperty(name)) var subindex = index[name]; else var subindex = index[name] = {}; subindex[person.age] = {}; } return index; }
Now we create an index for the second list of people:
var index2 = indexFrom(people2);
We also need a function to check if a person is on the list using his index:
function hasPerson(person, index) { var name = person.name; return index.hasOwnProperty(name) && index[name].hasOwnProperty(person.age); }
Finally, we can create a more efficient implementation of difference as follows:
function difference(a, index, has) { var m = a.length, c = []; for (var i = 0; i < m; i++) { var x = a[i]; if (!has(x, index)) c.push(x); } return c; }
You use it as follows:
console.log(difference(people, index2, hasPerson));
The advantage is that creating an index takes O(n) and calculating the difference takes O(m) time. Therefore, in the general case, this will take O(m + n) time instead of O(m * n) . In addition, you can cache the index for future use.
See demo: http://jsfiddle.net/F7RDs/1/
Hope this helps.