47

Given two arrays of unequal length:

var arr1 = ["mike", "sue", "tom", "kathy", "henry"]; //arr1.length = 5
var arr2 = ["howey", "jim", "sue", "jennifer", "kathy", "hank", "alex"]; //arr2.length = 7

How can I find the values common to both arrays? In this case "sue" and "kathy" should be returned.

0

4 Answers 4

60

Here is an intersection function based on Array.prototype.filter

function intersect(a, b) {
    var t;
    if (b.length > a.length) t = b, b = a, a = t; // indexOf to loop over shorter
    return a.filter(function (e) {
        return b.indexOf(e) > -1;
    });
}

var arr1 = ["mike", "sue", "tom", "kathy", "henry"];
    arr2 = ["howey", "jim", "sue", "jennifer", "kathy", "hank", "alex"];

intersect(arr1, arr2); // ["sue", "kathy"]

You might also want to consider the following

var arr1 = ['sue', 'sue', 'kathy'],
    arr2 = ['kathy', 'kathy', 'sue'];

The above would now give ["sue", "sue", "kathy"]. If you don't want duplicates you could do a further filter on this. This would also standardise results. i.e.

return a
    .filter(/* .. */) // same as before
    .filter(function (e, i, c) { // extra step to remove duplicates
        return c.indexOf(e) === i;
    });

Adding this will now return the same result as the previous arrays (["sue", "kathy"]), even though there were duplicates.

Sign up to request clarification or add additional context in comments.

7 Comments

Thanks Paul for giving both the remove dupes and regular options, Nice bit of code.
I dont believe this will work if one of the two arrays is empty, it will return a false positive...I simply did a check added a check for .length
Arghh.. I hate if (condition) return true; construction.. Why not return condition;?
@vp_arth to make it more obvious what's going on, of course feel free to modify it if you decide to use the code
[1],[1,1] shouldn't it return [1] ?
|
57

You could use Array.filter:

var result = arr1.filter(function(n) {
  return arr2.indexOf(n) > -1;
});

4 Comments

Why not just return arr2.indexOf(n) !== -1? You're making a new array either way.
@alex filter() returns array of matched values, while forEach does not return anything.
This should be marked as the accepted answer
@Blender 7 years later... "Why not just..." prolly conventional C/C++ paranoia.
25

You want to find the intersection of two arrays?

You could use Underscore's intersection(). This will give you a list of values present in both arrays.

var commonValues = _.intersection(arr1, arr2);

jsFiddle.

If you didn't want to use a library, it'd be trivial to implement...

var commonValues = arr1.filter(function(value) { 
                                   return arr2.indexOf(value) > -1;
                               });

jsFiddle.

If Array.prototype.filter() and Array.prototype.indexOf() are not supported in your target platforms...

var commonValues = [];
var i, j;
var arr1Length = arr1.length;
var arr2Length = arr2.length;

for (i = 0; i < arr1Length; i++) {
    for (j = 0; j < arr2Length; j++) {
        if (arr1[i] === arr2[j]) {
            commonValues.push(arr1[i]);
        }
    }
}

jsFiddle.

2 Comments

Reading this made me start thinking.. what should the expected result of an intersection be if you have "sue" appearing multiple times in one/both of the arrays?
@PaulS. Interesting thoughts. I guess this would add it multiple times if it were in the source array multiple times. If it were an issue, you could use a drop duplicates type method on the result (or factor it as you went in the above code).
9

Iterate over one of the arrays and compare the objects with the other:

var results = [];

for (var i = 0; i < arr1.length; i++) {
    if (arr2.indexOf(arr1[i]) !== -1) {
        results.push(arr1[i]);
    }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.