Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate intersection of multiple arrays in JavaScript? And what does [equals: function] mean?

People also ask

How do you find the intersection in Javascript?

Example 2: Perform Intersection Using filter() Method Each element of the first array is compared with the second array using the indexOf() method. The arr2. indexOf(x) method searches arr2 and returns the position of the first occurrence of arr1 . If the value cannot be found, it returns -1.

How do you print common elements in two arrays in Javascript?

Use the inbuilt ES6 function some() to iterate through each and every element of first array and to test the array. Use the inbuilt function includes() with second array to check if element exist in the first array or not. If element exist then return true else return false.


You could just use Array#reduce with Array#filter and Array#includes.

var array1 = ["Lorem", "ipsum", "dolor"],
    array2 = ["Lorem", "ipsum", "quick", "brown", "foo"],
    array3 = ["Jumps", "Over", "Lazy", "Lorem"],
    array4 = [1337, 420, 666, "Lorem"],
    data = [array1, array2, array3, array4],
    result = data.reduce((a, b) => a.filter(c => b.includes(c)));

console.log(result);

I wrote a helper function for this:

function intersection() {
  var result = [];
  var lists;

  if(arguments.length === 1) {
    lists = arguments[0];
  } else {
    lists = arguments;
  }

  for(var i = 0; i < lists.length; i++) {
    var currentList = lists[i];
    for(var y = 0; y < currentList.length; y++) {
        var currentValue = currentList[y];
      if(result.indexOf(currentValue) === -1) {
        var existsInAll = true;
        for(var x = 0; x < lists.length; x++) {
          if(lists[x].indexOf(currentValue) === -1) {
            existsInAll = false;
            break;
          }
        }
        if(existsInAll) {
          result.push(currentValue);
        }
      }
    }
  }
  return result;
}

Use it like this:

intersection(array1, array2, array3, array4); //["Lorem"]

Or like this:

intersection([array1, array2, array3, array4]); //["Lorem"]

Full code here

UPDATE 1

A slightly smaller implementation here using filter


This can be done pretty succinctly if you fancy employing some recursion and the new ES2015 syntax:

const array1 = ["Lorem", "ipsum", "dolor"];
const array2 = ["Lorem", "ipsum", "quick", "brown", "foo"];
const array3 = ["Jumps", "Over", "Lazy", "Lorem"];
const array4 = [1337, 420, 666, "Lorem"];

const arrayOfArrays = [[4234, 2323, 43], [1323, 43, 1313], [23, 34, 43]];

// Filter xs where, for a given x, there exists some y in ys where y === x.
const intersect2 = (xs,ys) => xs.filter(x => ys.some(y => y === x));

// When there is only one array left, return it (the termination condition
// of the recursion). Otherwise first find the intersection of the first
// two arrays (intersect2), then repeat the whole process for that result
// combined with the remaining arrays (intersect). Thus the number of arrays
// passed as arguments to intersect is reduced by one each time, until
// there is only one array remaining.
const intersect = (xs,ys,...rest) => ys === undefined ? xs : intersect(intersect2(xs,ys),...rest);

console.log(intersect(array1, array2, array3, array4));
console.log(intersect(...arrayOfArrays));

// Alternatively, in old money,

var intersect2ES5 = function (xs, ys) {
    return xs.filter(function (x) {
        return ys.some(function (y) {
            return y === x;
        });
    });
};
    
// Changed slightly from above, to take a single array of arrays,
// which matches the underscore.js approach in the Q., and is better anyhow.
var intersectES5 = function (zss) {
    var xs = zss[0];
    var ys = zss[1];
    var rest = zss.slice(2);
    if (ys === undefined) {
        return xs;
    }
    return intersectES5([intersect2ES5(xs, ys)].concat(rest));
};

console.log(intersectES5([array1, array2, array3, array4]));
console.log(intersectES5(arrayOfArrays));

Using a combination of ideas from several contributors and the latest ES6 goodness, I arrived at

const array1 = ["Lorem", "ipsum", "dolor"];
const array2 = ["Lorem", "ipsum", "quick", "brown", "foo"];
const array3 = ["Jumps", "Over", "Lazy", "Lorem"];
const array4 = [1337, 420, 666, "Lorem"];

Array.prototype.intersect = function intersect(a, ...b) {
    const c = function (a, b) {
        b = new Set(b);
        return a.filter((a) => b.has(a));
    };
    return undefined === a ? this : intersect.call(c(this, a), ...b);
};

console.log(array1.intersect(array2, array3, array4));
// ["Lorem"]

For anyone confused by this in the future,

_.intersection.apply(_, arrayOfArrays)

Is in fact the most elegant way to do this. But:

var arrayOfArrays = [[43, 34343, 23232], [43, 314159, 343], [43, 243]];
arrayOfArrays = _.intersection.apply(_, arrayOfArrays);

Will not work! Must do

var differentVariableName = _.intersection.apply(_,arrayOfArrays);