Posted on: March 01, 2023|Amrish Kushwaha

How to calculate the intersection of multiple arrays in JavaScript

How to calculate the intersection of multiple arrays in JavaScript

Using Map object (HashMap, extra storage) OR combinations of Array methods such as reduce filter and map, we can calculate the intersection of multiple arrays in javascript.

In our day-to-day life as developers, we come across many problems. One such problem is finding the intersection of arrays.

If the number of arrays is two and those arrays have either non-object elements in them such as strings, numbers etc, then it is quite easy to find the intersection of them. The complexity of the problem increases when we increase no of arrays i.e. more than 2 and the elements that those arrays contain are of object types.

The intersection in general:

The intersection of two or more arrays is an array of common elements found in all the arrays.

For example:

Let's say, there are 3 arrays, arr1, arr2 and arr3. Each array contains some elements in it as written below.

const arr1 = ["Item1", "Item2", "Item3", "Item4"]
const arr2 = ["Item3", "Item4", "Item5", "Item6", "Item7"]
const arr3 = ["Item3", "Item4", "Item8", "Item9"]

The intersection of all three arrays would be:

const intersection = ["Item3", "Item4"]

As you can see from the above code that the intersection of these arrays is an array of elements that are common to all arrays.

Similarly, if the elements are of type objects, then the intersection array of those arrays contains those objects which are present in all of the arrays.

Here are some real-life examples where intersections can be useful:

  1. Finding common elements in multiple arrays: Suppose you have multiple arrays of data and you need to find the elements that are common to all of them. By using the intersection operation, you can easily find the common elements and perform further operations on them.
  2. Set operations: The intersection operation is one of the set operations that can be performed on sets or arrays. You can use it to find the common elements between two sets or arrays.
  3. Data analysis: Intersections can be useful in data analysis when you need to compare two datasets and find the common elements or similarities between them.

In order to calculate the intersection of multiple arrays in javascript, we would go from easy problem to hard problem. It means that we would start by calculating the intersection of two arrays, and then keep increasing the level of the problem as we move further.

Calculate the intersection of two arrays of strings:

We will start by calculating the intersection of two arrays of strings.

So, let's say we have array1 and array2

const array1 = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]
const array2 = ["Item 3", "Item 4", "Item 5", "Item 2", "Item 7", "Item 8"]

We can calculate the intersection of arrays in two ways:

Using Map object:

Map is the object which is something like a directory. We can save key-value pairs in it and then we can retrieve them later whenever it is required.

So let's check the solution:

function getIntersection(arr1, arr2) {
const map = new Map()
const intersectMap = new Map()
for (let i = 0; i < arr1.length; i++) {
if (!map.has(arr1[i])) {
map.set(arr1[i], i)
}
}
for (let i = 0; i < arr2.length; i++) {
if (map.has(arr2[i]) && !intersectMap.has(arr2[i])) {
intersectMap.set(arr2[i], i)
}
}
return Array.from(intersectMap.keys())
}
const result = getIntersection(array1, array2)

And result:

console.log(result) // ["Item 3", "Item 4", "Item 5", "Item 2"]

As you can see above that I have used two Map objects. The first map object is used to set values (key-value pair) from the first array arr1. Here the key is the element and the value is its position in the array.

Once values are set in the map object. Now we go through each element in arr2 and check if that element is present in the map object as a key or not. If it is present, then save its value and index as key-value pair in intersectMap and if it is not present, then move on to the next element. Keep doing this and reach the end of the second array arr2.

Now intersectMap will contain all the common elements present in both arrays. Just return the keys of intersectMap and that would be our solution.

One interesting pattern we can see here is the elements in the intersection array follow the order of the second array array2 elements.

Using Array methods (filter, reduce and includes)

With using of array methods, we can also calculate the intersection:

function getIntersection(arr1, arr2) {
return [arr1, arr2]?.reduce((acc, currentValue) => {
return acc.filter(res => currentValue.includes(res))
})
}
const result = getIntersection(array1, array2)

And result:

console.log(result) // ["Item 2", "Item 3", "Item 4", "Item 5"]

As you can see from the above code, in the callback function of reduce method, I am filtering out those elements from the accumulator which are present in the second array which is currentValue.

One interesting pattern we can see here is the elements in the intersection array follow the order of the first array array1 elements.**

Now we go for a slightly higher level problem

Calculate the intersection of two arrays of objects:

Now we are going to calculate the intersection of two arrays of objects in javascript.

So let's say we have two arrays - array1 and array2.

const array1 = [
{ name: "Item 1" },
{ name: "Item 2" },
{ name: "Item 3" },
{ name: "Item 4" },
{ name: "Item 5" },
]
const array2 = [
{ name: "Item 5" },
{ name: "Item 4" },
{ name: "Item 6" },
{ name: "Item 3" },
{ name: "Item 7" },
]

We can calculate intersection in two ways:

Using Map object

Using the Map object, we can calculate the intersection of two arrays of objects like this:

function getIntersection(options, arr1, arr2) {
const key = options.key
const map = new Map()
const intersectMap = new Map()
for (let i = 0; i < arr1.length; i++) {
if (!map.has(arr1[i])) {
map.set(arr1[i][key], i)
}
}
for (let i = 0; i < arr2.length; i++) {
if (map.has(arr2[i][key]) && !intersectMap.has(arr2[i][key])) {
intersectMap.set(arr2[i][key], i)
}
}
return Array.from(intersectMap.keys()).map(res => {
return {
[key]: res,
}
})
}

Here we are passing options which contain the key as the first argument and the rest two arguments are arrays.

And result:

console.log(getIntersection({ key: "name" }, array1, array2))
// [{"name": "Item 5"}, {"name": "Item 4"}, { "name": "Item 3"}]

Here also, the first map object map will save the key-value pair from arr1 (individual object value as key and index as value) and the second map object intersectMap will extract the common elements from the second array arr2.

One interesting pattern we can see here is the elements in the intersection array follow the order of the second array array2 elements in the case when we are using the Map object.

Using Array methods (reduce, filter and find)

We can also calculate intersection using array methods:

function getIntersection(options, arr1, arr2) {
const key = options.key
return [arr1, arr2]?.reduce((acc, currentValue) => {
return acc?.filter(res =>
currentValue?.find(value => value[key] === res[key])
)
})
}

and result:

console.log(getIntersect({ key: "name" }, array1, array2))
// [ { name: "Item 3" }, { name: "Item 4" }, { name: "Item 5" }]

As you can see from the above code I am filtering the elements of the accumulator acc by finding it in currentValue.

One interesting pattern we can see here is the elements in the intersection array follow the order of the first array array1 elements.**

Calculate the intersection of multiple arrays of strings:

Now we go for some more generalized problems such as finding the intersection of multiple arrays of strings.

Now let's say we have a few arrays:

const arrstr__1 = [
"Item 1",
"Item 2",
"Item 3",
"Item 4",
"Item 5",
"Item 6",
"Item 7",
]
const arrstr__2 = ["Item 6", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7"]
const arrstr__3 = ["Item 4", "Item 7", "Item 5", "Item 6", "Item 8", "Item 9"]
const arrstr__4 = ["Item 7", "Item 5", "Item 6", "Item 8", "Item 9", "Item 10"]
const arrstr__5 = ["Item 6", "Item 7", "Item 5", "Item 8", "Item 9", "Item 10"]

Solving it using the Map object

We can solve this problem using the Map objects. I am going to use reduce method also because the number of arrays is not fixed, it is variable.

So, check the below solution:

function getIntersectMap(arr, map) {
const returnMap = new Map()
for (let i = 0; i < arr.length; i++) {
if (!map.size) {
returnMap.set(arr[i], i)
} else {
if (map.has(arr[i]) && !returnMap.has(arr[i])) {
returnMap.set(arr[i], i)
}
}
}
return returnMap
}
function getIntersection() {
const initialMap = new Map()
const arrays = Array.from(arguments) // I am assuming, all the arguments will be arrays.
const resultMap = arrays?.reduce(function _(acc, currentVal) {
return getIntersectMap(currentVal, acc)
}, initialMap)
return Array.from(resultMap.keys())
}

And the result is:

console.log(
getIntersection(arrstr__1, arrstr__2, arrstr__3, arrstr__4, arrstr__5)
)
// ["Item 6", "Item 7", "Item 5"]

As you can see from the above code I am assuming all the arguments will be arrays and I am applying the reduce method on the created array from arguments.

In the callback function of the reduce method, I am calculating the map object containing the common elements from the accumulator acc and currentValue which is an array and return it as a map object.

And finally, we get the result as a Map object and calculating the keys of that Map and converting it in the array will give the right solution.

One interesting pattern we can see here is the elements in the intersection array follow the order of the last array elements.

Solving it using Array methods (reduce, filter and find):

Now, let's use Array methods to solve it:

function getIntersection() {
const arrays = Array.from(arguments) // I am assuming all the arguments would be arrays.
return arrays?.reduce((acc, currentValue) => {
return acc.filter(res => currentValue.find(value => value === res))
})
}

And result:

console.log(
getIntersection(arrstr__1, arrstr__2, arrstr__3, arrstr__4, arrstr__5)
)
// ["Item 5", "Item 6", "Item 7"]

As you can see above, it is very easy to solve intersection problems using array methods. The above code is self-explanatory.

One interesting pattern we can see here is the elements in the intersection array follow the order of the first array elements.

Calculate the intersection of multiple arrays of objects:

Now we have come to the higher level problem.

Let's assume that we have a few arrays:

const arr__1 = [
{ name: "Item 1" },
{ name: "Item 2" },
{ name: "Item 3" },
{ name: "Item 4" },
{ name: "Item 5" },
{ name: "Item 6" },
{ name: "Item 7" },
]
const arr__2 = [
{ name: "Item 6" },
{ name: "Item 3" },
{ name: "Item 4" },
{ name: "Item 5" },
{ name: "Item 6" },
{ name: "Item 7" },
]
const arr__3 = [
{ name: "Item 4" },
{ name: "Item 7" },
{ name: "Item 5" },
{ name: "Item 6" },
{ name: "Item 8" },
{ name: "Item 9" },
]
const arr__4 = [
{ name: "Item 7" },
{ name: "Item 5" },
{ name: "Item 6" },
{ name: "Item 8" },
{ name: "Item 9" },
{ name: "Item 10" },
]
const arr__5 = [
{ name: "Item 6" },
{ name: "Item 7" },
{ name: "Item 5" },
{ name: "Item 8" },
{ name: "Item 9" },
{ name: "Item 10" },
]

Solving this problem would be similar to the solution of multiple arrays of strings. As we know already that we can solve it in two different ways, so let's check the solution one by one:

Solving it using the Map object

Again I am going to use reduce method along with the Map object.

function getIntersectMap(arr, map, key) {
const returnMap = new Map()
for (let i = 0; i < arr.length; i++) {
if (!map.size) {
returnMap.set(arr[i][key], i)
} else {
if (map.has(arr[i][key]) && !returnMap.has(arr[i][key])) {
returnMap.set(arr[i][key], i)
}
}
}
return returnMap
}
function getIntersection(option) {
const initialMap = new Map()
const key = option.key
const arrays = Array.from(arguments)?.slice(1) // I am assuming from the second arguments, rest all are arrays
const resultMap = arrays?.reduce(function _(acc, currentValue) {
return getIntersectMap(currentValue, acc, key)
}, initialMap)
return Array.from(resultMap.keys()).map(res => {
return {
[key]: res,
}
})
}

And the result:

console.log(
getIntersection({ key: "name" }, arr__1, arr__2, arr__3, arr__4, arr__5)
)
// [ { name: "Item 6" }, { name: "Item 7" }, { name: "Item 5" }]

In the callback function of the reduce method, I am calculating the map object containing the common elements from the accumulator acc and currentValue which is an array and return it as a map object.

And finally, we get the result as a Map object and calculating the keys of that Map and converting it in the array and mapping it with the right key-value pair will give the right solution.

The elements in the intersection array follow the order of the last array elements.

Solving it using Array methods (reduce, filter and find):

Now, let's use Array methods to solve it:

function getIntersection(option) {
const key = option.key
const arrays = Array.from(arguments)?.slice(1)
return arrays?.reduce((acc, currentValue) => {
return acc.filter(res =>
currentValue.find(value => value[key] === res[key])
)
})
}

And result:

console.log(
getIntersection({ key: "name" }, arr__1, arr__2, arr__3, arr__4, arr__5)
)
// [ { name: "Item 5" }, { name: "Item 6" }, { name: "Item 7" }]

As you can see above, it is very easy to solve intersection problems using array methods. The above code is self-explanatory.

The elements in the intersection array follow the order of the first array elements.

You can see that how easy it is to calculate the intersection of multiple arrays of objects once you start solving the easy problem first and then move to the difficulties level as you further go.

I hope that you have liked the article.

Thanks for reading it. Keep coding and keep solving problems.

About author:

Amrish Kushwaha

Amrish Kushwaha

I am Amrish Kushwaha. Software Engineer, Maker, Writer. I am currently focused on frontend development with curiosity of building end to end software system. Currently I am working at Rafay Systems. I love to write as well as build side projects when I am free.

Related category articles: