Viren Bhagat

Solving "Sorted Union" / freeCodeCamp Algorithm Challenges

7/23/2020

'Sorted Union'

Let's solve freeCodeCamp's intermediate algorithm scripting challenge, 'Sorted Union'.

Starter Code

function uniteUnique(arr) {
  return arr;
}

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

Instructions

Write a function that takes two or more arrays and returns a new array of unique values in the order of the original provided arrays.

In other words, all values present from all arrays should be included in their original order, but with no duplicates in the final array.

The unique numbers should be sorted by their original order, but the final array should not be sorted in numerical order.

Check the assertion tests for examples.

Test Cases

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]) should return [1, 3, 2, 5, 4].
uniteUnique([1, 2, 3], [5, 2, 1]) should return [1, 2, 3, 5].
uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]) should return [1, 2, 3, 5, 4, 6, 7, 8].

Our Approach

We have a short set of instructions for this one. After reading and looking at the test cases,

  • We have one input, arr, but there are more than one arguments in the function given.
  • We must return an array.
  • We have to create an array of the values of the arrays in arguments, but in the original order and also no duplicates.

To clarify it a little better, we can look at one of the test cases -

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]) should return [1, 3, 2, 5, 4]

// 3 arrays in arguments
// 1 and 2 are in every array but we just take the one we see first
// first arg is [1,3,2] so we enter those values in that order in our new array
// moving on to the second array, 5 is new, so we can add that into the new array
// 2 and then 1 are already in so we do not want to add them in as they'd be duplicates
// 4 is new, lets add that
// the third array, [2,1], are already in the array so disregard

So with that, let's start trying to solve this.

The first thing I'd like to work on is the arguments. Looking at the provided code and test cases, we have arr, but each test case has more than one array. How can we access all of the arrays?

function uniteUnique(arr) {
  console.log(arr);
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);
// [1, 3, 2]
// The console.log(arr) is only going to output the first array

Enter in the arguments object. I always find the MDN web docs to be helpful.

"arguments is an Array-like object accessible inside functions that contains the values of the arguments passed to that function." - MDN

Looking at a little sample helps, let's use the above again -

function uniteUnique(arr) {
  console.log(arr);
  console.log(arguments);
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);
//console.log(arr)  -- [1, 3, 2]
// console.log(arguments) -- { '0': [ 1, 3, 2 ], '1': [ 5, 2, 1, 4 ], '2': [ 2, 1 ] }

arguments gives us all the values back in an object. For the sake of this challenge, I think it would be easier to work with these values in an array instead of an object so we can use the spread syntax.

function uniteUnique(arr) {
  const arrArgs = [...arguments]
  console.log(arrArgs);
}

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

So we now have an array of arrays not an object of arrays.

My next action is to create an empty array to hold our new array.

const union = [];

We can now think about how we should loop through arrArgs and what to push into union.

So, we want to add unique values only and ensure we add them in the order we encounter them. Since there are subarrays in arrArgs, I think I would opt for a for loop and have to place another for loop inside to access the subarrays.

To check if the item already exists in our new array, we can use indexOf() as it is a good way to check.

Array.indexOf() on MDN

for (let i = 0; arrArgs.length; i++) {
  for (let j = 0; arrArgs[i].length; j++) {
    if (union.indexOf(arrArgs[i][j]) == -1) {
      union.push(arrArgs[i][j])
    } 
  }
}

In the above, we are checking to see if each value exists in union. If it returns true, we can push() it into union. If the if statement returns false, we move on to the next item.

Ensure we return union and that should be all.

Our Solution

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

Links & Resources

'Sorted Union' Challenge on fCC

freeCodeCamp

Donate to FCC!

Solution on my GitHub

Thank you for reading!

fcc, javascript, algorithms