9

I have arrays like;

var john = { name: "John Smith", age: 23 };
var mary = { name: "Mary Key", age: 18 };
var bob = { name: "Bob-small", age: 6 };
var people = [john, mary, bob];

var john2 = { name: "John Smith", age: 23 };
var people2 = [john2];

What I would like to do is subtract people2 from people and get result;

[mary, bob];

How can I achieve this? TIA

bsaglamtimur
  • 385
  • 1
  • 7
  • 17
  • 1
    [.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) – Andreas Feb 02 '14 at 10:31
  • 3
    Read [What is the fastest or most elegant way to compute a set difference using Javascript arrays?](http://stackoverflow.com/questions/1723168/what-is-the-fastest-or-most-elegant-way-to-compute-a-set-difference-using-javasc) – Grijesh Chauhan Feb 02 '14 at 10:34

3 Answers3

8

The difference of two sets, A and B, is defined as the set of all those elements of A which are not in B. If we implement it naively, computing the difference of two sets of sizes m and n respectively would take O(m * n) time. Not very efficient:

const john1 = { name: "John Smith", age: 23 };
const john2 = { name: "John Smith", age: 23 };
const mary = { name: "Mary Key", age: 18 };
const bob = { name: "Bob-small", age: 6 };

const people1 = [john1, mary, bob];
const people2 = [john2];

const eqPerson = (p, q) => p.name === q.name && p.age === q.age;

const result = people1.filter(p => people2.every(q => !eqPerson(p, q)));

console.log(result); // [mary, bob]

Fortunately, there's a faster way to compute the set difference for large sets using hashing.

const john1 = { name: "John Smith", age: 23 };
const john2 = { name: "John Smith", age: 23 };
const mary = { name: "Mary Key", age: 18 };
const bob = { name: "Bob-small", age: 6 };

const people1 = [john1, mary, bob];
const people2 = [john2];

const hashPerson = ({ name, age }) => `${name} ${age}`;

const hashSet = new Set(people2.map(hashPerson));

const result = people1.filter(p => !hashSet.has(hashPerson(p)));

console.log(result); // [mary, bob]

The advantage is that creating a hash set takes O(n) time and calculating the difference takes O(m) time. Hence in total it only takes O(m + n) time instead of O(m * n) time. In addition, you can reuse the hash set in the future.

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • Nice explanation, Yes I don't understand `arguments.length` where does `arguments` come? May be very silly question but I am kinda new to Web-stuffs. Can you also tell me what does `hasOwnProperty` means? – Grijesh Chauhan Feb 02 '14 at 11:37
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments – Aadit M Shah Feb 02 '14 at 13:10
5

Here is an easy solution:

var diff = people.filter(function(item) {
  return !people2.some(function(test){
    return test.name === item.name && test.age === item.age;
  });
});

Make sure the function passed to people2.some correctly checks that the two objects are equal, since == would fail, as you have references to different objects with identical properties.

Tibos
  • 27,507
  • 4
  • 50
  • 64
0

So, here goes the final running code. Copy , paste it and check for the output.It is first of all separating the strings (comma-separation). Then it is comparing them individually . Check this link: http://jsfiddle.net/DXRZ4/

<html>
  <head>
    <script>
        var a = new Array(); var i=1; var people = new Array();
        function fun() {
            var str = "john,john,bob",
                l = str.split(",");
            for(i=0; i<3; i++) {
                a[i] = l[i];
                // this will show the comma separated strings
                document.writeln(l[i]);
            }
            for(i=0; i<3; i++) {
                t=a[i]; 
                j=a[i+1];
                if((a[i]==a[i+1]) || (a[i]==a[i+2])) {
                    // it will store the position of string which are same
                    p=i; 
                }
            }
            for(i=0; i<3; i++) { 
                if(p!=i){
                    document.writeln("Subtracted Strings are:-");
                    document.writeln(l[i]);
                }
            }
        }
    </script>
  <body>
    <input type="button" name="b1" onClick="fun()">
  </body>
</html>
Sparkup
  • 3,686
  • 2
  • 36
  • 50
user2804021
  • 151
  • 5
  • 1
    Why don't you create a [fiddle](http://jsfiddle.net/) for the reader instead of expecting them to copy/paste your code? – Aadit M Shah Feb 02 '14 at 11:19