admin管理员组

文章数量:1400148

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]

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]
Share Improve this question edited Dec 15, 2018 at 15:27 leonardofed asked Dec 15, 2018 at 15:24 leonardofedleonardofed 9862 gold badges9 silver badges26 bronze badges 2
  • 2 Did you think about using sets instead? Something like this: jsfiddle/briosheje/y03osape/1 Array.from(new Set([...arrays].flat())); – briosheje Commented Dec 15, 2018 at 15:26
  • 1 What does mean union for you? I would expect the result of [5, 15]. – kind user Commented Dec 15, 2018 at 15:32
Add a ment  | 

4 Answers 4

Reset to default 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:

  • Array.from takes an Iterable as an argument, this will create a new array from the original one.
  • [...arrays] spreads the arrays (argument) into a new, single, one (So it bees an array of arrays) -> [5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5] bees: [[5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]]
  • .flat flattens the array, making that an array of values rather than ar array of arrays of values -> https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat -> [[5, 10, 15], [15, 88, 1, 5, 7], [100, 15, 10, 1, 5]] bees [5, 10, 15, 15, 88, 1, 5, 7, 100, 15, 10, 1, 5]
  • new Set removes duplicates from the array and returns an Iterable https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set. -> [5, 10, 15, 15, 88, 1, 5, 7, 100, 15, 10, 1, 5] bees a Set instance (an Iterable) without the duplicates. Array.from then converts the Set (Iterable) to a regular array. Further infos here: How to convert Set to Array?

BEWARE: Array.flat is currently an experimental feature (https://developer.mozilla/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/briosheje/y03osape/2/

Snippet without .flat: http://jsfiddle/briosheje/y03osape/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);

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 mon
  var intersection = input.shift();
  var remove = [];

  // loop over items in first array and attempt to
  // disprove monality
  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);

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.

本文标签: javascriptUnion between three arraysStack Overflow