2

I need to find the union of three arrays that get passed to the function union.

It took me about 50lines to code to get the expected result. Apparently, the following code works but now I wonder what are the best ways (either in a functional and in a non-functional fashion) to do the same job.

function union(...arrays) {
    var array1 = arguments[0];
    var array2 = arguments[1];
    var array3 = arguments[2];      

    var unique = [];
    var intersaction = [];

    // find the unique values

    for(let i = 0; i < array1.length; i++) {
        if( (array2.includes(array1[i]) == false) && (array3.includes(array1[i])) == false ) {
            unique.push(array1[i]); 
        }
    }

    for(let i = 0; i < array2.length; i++) {
        if( (array1.includes(array2[i]) == false) && (array3.includes(array2[i])) == false ) {
            unique.push(array2[i]); 
        }
    }

    for(let i = 0; i < array3.length; i++) {
        if( (array1.includes(array3[i]) == false) && (array2.includes(array3[i])) == false ) {
            unique.push(array3[i]);
        }
    }

    // find the intersection

    for(let j = 0; j < array1.length; j++) {
        if(array2.includes(array1[j]) || array3.includes(array1[j]) ) {
            if (intersaction.indexOf(array1[j]) == -1) { 
                intersaction.push(array1[j]);
            }
        }
    }

    for(let j = 0; j < array2.length; j++) {
        if(array1.includes(array2[j]) || array3.includes(array2[j]) ) {
            if (intersaction.indexOf(array2[j]) == -1) { 
                    intersaction.push(array2[j]);
            }       
        }
    }

    for(let j = 0; j < array3.length; j++) {
        if(array1.includes(array3[j]) || array2.includes(array3[j]) ) {
            if (intersaction.indexOf(array3[j]) == -1) { 
                    intersaction.push(array3[j]);
            }       
        }
    }

    return union = [...intersaction, ...unique];

}

console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));
// should log: [5, 10, 15, 88, 1, 7, 100]
leonardofed
  • 696
  • 6
  • 20
  • 2
    Did you think about using **sets** instead? Something like this: http://jsfiddle.net/briosheje/y03osape/1/ `Array.from(new Set([...arrays].flat()));` – briosheje Dec 15 '18 at 15:26
  • 1
    What does mean _union_ for you? I would expect the result of `[5, 15]`. – kind user Dec 15 '18 at 15:32

4 Answers4

5

Just another solution keeping the original function signature provided by the OP:

function union(...arrays) {
    return Array.from(new Set([...arrays].flat()));
}

console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));

Or, even shorter (but less read friendly):

return [...(new Set([...arrays].flat()))];

Explanation:

BEWARE: Array.flat is currently an experimental feature (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat). Solution without using flat below:

function union(...arrays) {
    return Array.from(new Set([].concat.apply([],[...arrays])));
}

console.log(union([5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]));

Explanation (only differences from above):

  • Instead of .flat, we apply to Array.concat our original array, so that it will flatten it passing a new array as its this and providing our array as the argument: [].concat.apply([],[...arrays])

Snippet: http://jsfiddle.net/briosheje/y03osape/2/

Snippet without .flat: http://jsfiddle.net/briosheje/y03osape/4/

briosheje
  • 6,538
  • 2
  • 31
  • 48
4

use set that's very simple,

The Set object lets you store unique values of any type, whether primitive values or object

var a=  [5, 10, 15];
var b=[15, 88, 1, 5, 7];
var c=[100, 15, 10, 1, 5];
var result= [...new Set([...a, ...b,...c])];
console.log(result);
Just code
  • 12,567
  • 10
  • 45
  • 82
1

I tried to copy your approach of looping over arrays but in a slightly more efficient manner, using only ES5 safe functions. I'm sure the other answers are more efficient if you can use the features they do.

var a = [1, 2, 3];
var b = [1, 2, 4, 5];
var c = [2, 7, 9];

// takes an array of arrays
function getUnique(input) {

  var unique = [];

  // loop over each array
  input.forEach(function(item) {
    // loop over each value
    item.forEach(function(value) {
      // if it's not already in the unique array,
      if (unique.indexOf(value) == -1) {
        // add it
        unique.push(value);
      }
    });
  });

  return unique;
}

// takes an array of arrays
function getIntersection(input) {

  // assume all elements in first array are common
  var intersection = input.shift();
  var remove = [];

  // loop over items in first array and attempt to
  // disprove commonality
  intersection.forEach(function(value) {

    // loop over subsequent arrays
    for (var i = 0; i < input.length; i++) {
      var item = input[i];
      // if these arrays don't contain the value, 
      // then it isn't an intersection
      if (item.indexOf(value) == -1) {
        // add it to an array to be removed
        remove.push(value);
        // exit this loop
        break;
      }
    }
  });

  // remove values determined not to be intersections
  remove.forEach(function(value) {
    intersection.splice(intersection.indexOf(value), 1);
  })

  return intersection;
}


var test = getUnique([a, b, c]);

console.log(test);

var test2 = getIntersection([a, b, c]);

console.log(test2);
sauntimo
  • 1,129
  • 1
  • 14
  • 21
0

Based on custom forEach and Reduce from previously in the exercise at http://csbin.io/callbacks

function forEach(array, callback) {
    for(i = 0; i < array.length; i++){
        callback(array[i])
    }
}

function reduce(array, callback, initialValue) {
    for(let i of array){
        initialValue = callback(initialValue, i)
    }
    return initialValue
}

function union(...arrays) {
    return reduce(arrays, (seen, next) => {
        forEach(next, (element) => {
            if(!seen.includes(element)) seen.push(element);
        })
        return seen
    }, [])
}

Note if you use the in-built reduce function you can remove the empty inital array requirement.

Carl Aiau
  • 21
  • 3