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 onearguments
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 anArray
-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.
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
Thank you for reading!
Top comments (2)
i have tried something more simple you can see below....
function uniteUnique(arr) {
let array = [].concat.apply([], [...arguments])
return Array.from(new Set(array));
}
uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);
better yet:
function uniteUnique(arr) {
return [...new Set([...arguments].flat())]
}