freeCodeCamp Algorithm Challenge Guide: Sorted Union

freeCodeCamp Algorithm Challenge Guide: Sorted Union
0

#1

:triangular_flag_on_post: Remember to use Read-Search-Ask if you get stuck. Try to pair program :busts_in_silhouette: and write your own code :pencil:

:checkered_flag: Problem Explanation:

The program has to return a new array of unique values from two original arrays in the order they show up. So there is not sorting required, and there shouldn’t be any duplicates.

Relevant Links

:speech_balloon: Hint: 1

Since you have no idea how many parameters were passed, it would be best to loop through the arguments before looping through the arrays.

try to solve the problem now

:speech_balloon: Hint: 2

It isn’t necessary to use loops. You can use functions such as map(), reduce() or others if you want.

try to solve the problem now

:speech_balloon: Hint: 3

You will have to check if the current value is already on the array to be returned for every value.

try to solve the problem now

Spoiler Alert!

687474703a2f2f7777772e796f75726472756d2e636f6d2f796f75726472756d2f696d616765732f323030372f31302f31302f7265645f7761726e696e675f7369676e5f322e676966.gif

Solution ahead!

:beginner: Basic Code Solution:

function uniteUnique(arr1, arr2, arr3) {
  // Creates an empty array to store our final result.
  var finalArray = [];

  // Loop through the arguments object to truly made the program work with two or more arrays
  // instead of 3.
  for (var i = 0; i < arguments.length; i++) {
    var arrayArguments = arguments[i];

    // Loops through the array at hand
    for (var j = 0; j < arrayArguments.length; j++) {
      var indexValue = arrayArguments[j];

      // Checks if the value is already on the final array.
      if (finalArray.indexOf(indexValue) < 0) {
        finalArray.push(indexValue);
      }
    }
  }

  return finalArray;
}

// test here
uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);

:rocket: Run Code

Code Explanation:

  • Create empty array finalResult to store the final result.
  • Loop through the arguments object in the outer loop and store it in arrayArguments.
  • The inner loop is used to loop through individual array elements.
  • If the element doesn’t already exist in finalArray, add it.
  • Return finalArray.

Relevant Links

:sunflower: Intermediate Code Solution:

function uniteUnique(arr1, arr2, arr3) {
 var newArr;
 //Convert the arguments object into an array
  var args = Array.prototype.slice.call(arguments);
  //Use reduce function to flatten the array
  newArr = args.reduce(function(arrA,arrB){
  //Apply filter to remove the duplicate elements in the array
    return arrA.concat(arrB.filter(function(i){
      return arrA.indexOf(i) === -1;
    }));
  });

   return newArr;                    
}

// test here
uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);

:rocket: Run Code

Code Explanation:

  • arguments object is converted into an array using slice().
  • reduce() function is used to flatten the array i.e., for every element that is in the array (or nested arrays), extract it’s elements into one-dimensional array.
  • After flattening the array, filter() is used to remove duplicate elements from newArr.

Relevant Links

:rotating_light: Advanced Code Solution:

function uniteUnique() {
  var concatArr = [];
  var i = 0;
  while (arguments[i]){
    concatArr = concatArr.concat(arguments[i]); i++;
  }
  uniqueArray = concatArr.filter(function(item, pos) {
    return concatArr.indexOf(item) == pos;
  });
  return uniqueArray;
}

// test here
uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);

:rocket: Run Code

Code Explanation:

  • Number of arguments can change dynamically, so we don’t need to bother providing our function uniteUnique() with arguments at all.
  • We use a while loop to concatenate all the arguments into one array called concatArr.
  • We use filter() to remove the duplicate elements by checking the index of each element and removing same elements with different positions.
  • Ordering will be preserved here.

Relevant Links

:rotating_light: Alternative Code Solution using ES2015

//jshint esversion:6

function uniteUnique(arr) {
  
  //make an array out of arguments and flatten it (using the spread operator)
  const args = [].concat(...arguments);
  
  // create a Set
  return [...new Set(args)];
}

// test here
uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);

:rocket: Run Code

Code Explanation:

  • We first use concat() with an empty array [] as a starting point and the spread operator ... to create an array out of the Arguments object and to flatten it at the same time
  • then we use the new ES2015 Set object to store only unique values
  • (to learn more about Sets, read here)

Relevant Links

:clipboard: NOTES FOR CONTRIBUTIONS:

  • :warning: DO NOT add solutions that are similar to any existing solutions. If you think it is similar but better, then try to merge (or replace) the existing similar solution.
  • Add an explanation of your solution.
  • Categorize the solution in one of the following categories — Basic, Intermediate and Advanced. :traffic_light:
  • Please add your username only if you have added any relevant main contents. (:warning: DO NOT remove any existing usernames)

See :point_right: Wiki Challenge Solution Template for reference.


#2

#3

#4
function uniteUnique(arr) {
  var args = Array.from(arguments);
  var uniqueValues = [];

  for (var i = 0; i < args.length; i++) {
    for (var j = 0; j < args[i].length; j++) {
      if (!uniqueValues.includes(args[i][j])) {
        uniqueValues.push(args[i][j]);
      }
    }
  }

  return uniqueValues;
}

#5

Here’s mine:

function uniteUnique(arr) {
  var uniqueArr = Array.from(arguments).reduce(function(a, b) {
    return a.concat(b);
  }, []);

  var i = 0, max = uniqueArr.length;
  
  while(i < max) {
    max = uniqueArr.length;
    
    for(var j = i + 1; j < max; j++) {
      if(uniqueArr[i] === uniqueArr[j]) {
        uniqueArr.splice(j, 1);
      }      
    }    
    i++;
  }
  
  return uniqueArr;
}

#6

Here’s mine.

I used a spread operator to assign all arrays in the arguments object to one array, then iterated over them with reduce and find to remove the duplicate results.

function uniteUnique(arr) {
  const numbers = [].concat(...arguments);
  return numbers.reduce(function(reducedNumbers, number){
  	if (!reducedNumbers.find(reducedNumber => { return reducedNumber === number; })) {
    	reducedNumbers.push(number);
    }
    return reducedNumbers;
  }, []);
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);

#7

How does this look for the advanced solution?

function uniteUnique() {

  return (
    //Get all the arguments into an array
    Array.from(arguments)
    
    //Flatten the arrays within the array
    .reduce(function(a, b){ 
      return a.concat(b);}, [])
    
    //Filter out the duplicates
    .filter(function(val, i, arr){ 
      return arr.indexOf(val) == i;})
  )
}

#8

This also works. We can grab all arguments with …arr, run concat on the array, and then filter it out on the go.

function uniteUnique(...arr) {
          return arr.reduce(function(all,item){
             return all.concat(item).filter(function(el,index,self){
                 return index == self.indexOf(el);
             });
          });
        }

#9

Nice code, but I think the solution above yours is better, since you call ‘.filter()’ after every ‘.concat()’, which is unnecessary (and thus less efficient).


#10

My one line solution

function uniteUnique(...arr) {
  return arr.reduce((a, c)=>a.concat(c.filter(v => a.indexOf(v) == -1)),[]);
}

#11

This is my solution using ES6

   function uniteUnique(arr) {

    function remove_duplicates_es6(arr) {
        let s = new Set(arr);
        let it = s.values();
        return Array.from(it);
    }

    let newArr = [];

    newArr.push(arguments);

    for (let i in newArr) {

        let array = $.map(newArr[i], function(value, index) {
            return [value];
        });
        let flattened = array.reduce((a, b) => a.concat(b), []);
        return remove_duplicates_es6(flattened);

    }

}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);

or just the oneliner

return [...new Set(Array.from(arguments).reduce((a, b) => a.concat(b)))];


#12

my red-headed stepchild:


function uniteUnique(arr) {
  var arr1 = [];
  for(var i of arguments) {
    for(var k of i) {
      if(arr1.indexOf(k) === -1) {
        arr1.push(k);
      }
    }
  }
  arr = arr1;
  return arr;
}


#13

My solution :slight_smile:
function uniteUnique(arr) {
var args = Array.prototype.slice.call(arguments),finalArr=[];

  for(var i=0;i<args.length;i++){
   args[i].forEach(function(element){
       if(!finalArr.includes(element)){
         finalArr.push(element);
       }
    });
    
  }
  return finalArr;
}

#14

My Code:

function uniteUnique(arr) {
  //get the first parameter to compare arrays to
  var arr1 = arguments[0];
  //loop through arguments
  for(var i=1; i<arguments.length; i++){
    var arg = arguments[i];
    //loop through each argument array
    for(var y=0; y<arg.length; y++){
      while(arr1.indexOf(arg[y]) != -1){
        arg.splice(y, 1);//remove all dublicates from current argument
      }
    }
    arr1 = arr1.concat(arg);//concatenate arrays with no dublicates
  }
  return arr1;
}
//test
uniteUnique([1, 3, 2], [1, [5]], [2, [4]]);

#15

Why cannot we make use of Map ?


#16

I over-complicated it after mis-reading the prompt. But, this one will flatten all of the arrays before putting them in place, so you end up with just a single-level array. Now to go back and remove all the flattening so it meets the criteria to move on :slight_smile:

function flatten(arr){
  return arr.reduce(function(accum, val){
    if(Array.isArray(val)){
      return accum.concat(flatten(val)); //recursion on arrays
    }else{
      return accum.concat(val);
    }
  },[]);
}

function uniteUnique(arr) {
  var retArr =[];
 
  for (var i=1; i<arguments.length;i++){ //start at 1 b/c arr includes 0 index
    arr.push(flatten(arguments[i]));
  }//array of flat arrays
  
  arr = flatten(arr); //now a flat array
  
  for (i=0;i<arr.length;i++){
    if(!retArr.includes(arr[i])){
      retArr.push(arr[i]);
    }
     
  }
  
  return retArr;
}

console.log(uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]));
console.log(uniteUnique([1,3,2],[1,[5]],[2,[4]]));

#17

You can use map. Check out my solution here:

function uniteUnique(arr) {
  var newArr = [];
  var arg = [].slice.call(arguments);
  
  function onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
  }
  
  arg.map(function(val){
    val.map(function(ind){
      newArr.push(ind);
    });
  });
  
  return newArr.filter(onlyUnique);
}

#18

Couple of my solutions - bottom one was what I came up with first, the second was just to try to use reduce since it was offered as a hint:

function test(...arg) { 
  let x = arg.reduce((prv, cur) => prv.concat(cur)),
  y = x.filter((v,p) => (v != undefined) ? x.indexOf(v) == p : undefined)
  console.log(y)
}

test([1, 2, 3], [5, 2, 1]);




function uniteUnique(arr) { 
  const arg0 = arguments[0],
        arg1 = arguments[1],
        arg2 = arguments[2],
        arg3 = arguments[3],
        
        concatArr = arg0.concat(arg1, arg2, arg3);
  
  let output = concatArr.filter((elem, pos) => {
    if (elem != undefined) {
      return concatArr.indexOf(elem) === pos;
    }
  });
  
  console.log(output);
  return output
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);

#19

function uniteUnique(arr) {
var args = Array.from(arguments);
var newArr = [];
for (var k = 0; k < args.length; k++) {
newArr = newArr.concat(args[k]);
}
for (var i = 0; i < newArr.length; i++) {
for (var j = i + 1; j < newArr.length; j++) {
if (newArr[i] === newArr[j]) {
newArr.splice(j, 1);
i–;
}
}
}
return newArr;
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);


#20

I thought I came up with an original solution but then I came here it’s pretty similar to all the others :laughing:. Good to know I’m on the right track though. I’m really enjoying these challenges.


function uniteUnique(arr) {
 var newArr = arguments[0];
  for (var i = 0; i < arguments.length; i++){
    for (var j = 0; j < arguments[i].length; j++){
      if (newArr.indexOf(arguments[i][j]) === -1){
 newArr.push(arguments[i][j]);
   }
  }
 }
  return newArr;
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);