0

Construct a function intersection that compares input arrays and returns a new array with elements found in all of the inputs.

My solution works but it is very cumbersome:

const intersection = (arrMerged) => {

  let finalArr = []; 
  let flatArray = [].concat(...arrMerged)

  let newArr = []; 
  //console.log(flatArray)

  //let interArray = []; 

  if (arrMerged[2] !== undefined){

    newArr = arrMerged[0].map((elem) => {
      if (arrMerged[1].includes(elem) && arrMerged[2].includes(elem)){
        return elem; 
      }
    })
  }

  else {
    newArr = arrMerged[0].map((elem) => {
      if (arrMerged[1].includes(elem)){
        return elem; 
      }
    })
  }


  newArr.forEach((elem) => {
    if (elem !== undefined){
      finalArr.push(elem)
    }
  })
  return finalArr; 
}

// Uncomment these to check your work!
const arr1 = [5, 10, 15, 20];
const arr2 = [15, 88, 1, 5, 7];
const arr3 = [1, 10, 15, 5, 20];

console.log(intersection([arr1, arr2, arr3])); // should log: [5, 15]

I would also like to use reduce() in my solution. Can someone provide an alternative code solution that uses reduce() and is more efficient please?

I would appreciate it if you can comment on what each line of your code is doing to help me understand.

PineNuts0
  • 4,740
  • 21
  • 67
  • 112

3 Answers3

2

You could use reduce like this:

const intersection = (arrays) =>
    arrays.reduce((a, b) =>
        a.filter(c => b.some(d => c === d)) 
    );

The filter part performs the intersection of two given arrays a and b. The reduce part applies this logic by taking the next array from the input and intersecting it with the previous result.

This is not the most optimal way however. Use a Set for better performance when using huge arrays.

const intersection = (arrays) =>
    arrays.reduce((a, b) => {
        const set = new Set(b);
        return a.filter(c => set.has(c)); 
    });

For more on that, see the answer to this question -- dealing with just two arrays as input.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • I'm a bit confused: what is the code below doing? a.filter(c => b.some(d => c === d)) – PineNuts0 Jun 14 '19 at 17:44
  • @PineNuts0, `filter` iterates the `a` array, and returns a new array that has the values for which the expression `b.some(d => c === d)` is true. `b.some` iterates the other, `b`, array, and returns true when it finds at least on element that satisfies `c === d`. – trincot Jun 14 '19 at 17:56
0

You can take first index array and match it with every other array and filter value based accordingly

const arr1 = [5, 10, 15, 20];
const arr2 = [15, 88, 1, 5, 7];
const arr3 = [1, 10, 15, 5, 20];

const intersection = (arr) => {
  let [a,...rest] = arr
  return a.filter(v=> rest.every(val => val.includes(v)))
}

console.log(intersection([arr1, arr2, arr3]));
Code Maniac
  • 37,143
  • 5
  • 39
  • 60
-1

You can use filter() on any of the subarray. And use nested every() on the main array.

const arr1 = [5, 10, 15, 20];
const arr2 = [15, 88, 1, 5, 7];
const arr3 = [1, 10, 15, 5, 20];

const intersection = arr => arr[0].filter(x => arr.every(a => a.includes(x)));

console.log(intersection([arr1,arr2,arr3]))

Explanation:

See the code :

arr[0].filter(x => arr.every(a => a.includes(x)));

The word explanation for this will. Its filtering out only those elements of the first subarray(arr[0]) which are included in every other subarray.

Array.prototype.every() takes a callback as parameter. First element of the callback will be the element itself. In the above case a will be the arr1,arr2,arr3.

arr.every(a => a.includes(x)) checks whether the current element of the first array. 5,10,15,20 is present in all the other arrays

There are nested loops in the above version. If you want more efficient solution you can first convert all the arrays except first to Set and then use Set.has

const arr1 = [5, 10, 15, 20];
const arr2 = [15, 88, 1, 5, 7];
const arr3 = [1, 10, 15, 5, 20];

const intersection = arr => {
  let [first,...rest] = arr;
  rest = rest.map(x => new Set(x));
  return first.filter(x => rest.every(a => a.has(x)));


} 
console.log(intersection([arr1,arr2,arr3]))
Community
  • 1
  • 1
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
  • thank you; what is the code below doing? x => arr.every(a => a.includes(x)) – PineNuts0 Jun 14 '19 at 17:48
  • 1
    @PineNuts0 I have added an explanation. Ask if you don't understand some thing. – Maheer Ali Jun 14 '19 at 17:53
  • 1
    Strange, the question was about using `reduce`, and this answer gets accepted. I am confused. – trincot Jun 14 '19 at 18:01
  • 1
    @trincot Well I can't why is it so. Sometimes new users don't know about much about higher order array methods. They just know name of one of them and they ask that in the question. They have no idea about most appropriate method for their purpose. – Maheer Ali Jun 14 '19 at 18:07