 # freeCodeCamp Challenge Guide: Sorted Union

freeCodeCamp Challenge Guide: Sorted Union
0

# Sorted Union

## 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.

## Hints

### 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.

### Hint 2

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

### Hint 3

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

## Solutions

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

// Loop through the arguments object to truly make the program work with two or more arrays
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]);
``````

#### 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.
• Return finalArray.

Solution 2 (Click to Show/Hide)
``````function uniteUnique(arr) {
var args = [...arguments];
var result = [];
for (var i = 0; i < args.length; i++) {
for (var j = 0; j < args[i].length; j++) {
if (!result.includes(args[i][j])) {
result.push(args[i][j]);
}
}
}
return result;
}

uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);
``````
Solution 3 (Click to Show/Hide)
``````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]);
``````

#### 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.

Solution 4 (Click to Show/Hide)
``````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]);
``````

#### 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.

Solution 5 (Click to Show/Hide)

Alternative Code Solution using ES2015

``````//jshint esversion:6

function uniteUnique(...arrays) {
//make an array out of the given arrays and flatten it (using the spread operator)
const flatArray = [].concat(...arrays);

// create a Set which clears any duplicates since it's a regulat set and not a multiset
return [...new Set(flatArray)];
}

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

#### 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

7 Likes
``````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;
}
``````
23 Likes

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;
}``````
1 Like

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]);``````

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;})
)
}``````
7 Likes

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);
});
});
}``````
1 Like

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).

My one line solution

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

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)))];`

1 Like

``````
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;
}

``````
4 Likes

My solution 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;
}``````
1 Like

My Code:

``````function uniteUnique(arr) {
//get the first parameter to compare arrays to
var arr1 = arguments;
//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, ], [2, ]);``````

Why cannot we make use of Map ?

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 ``````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,],[2,]));``````

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);
}``````

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,
arg1 = arguments,
arg2 = arguments,
arg3 = arguments,

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]);``````

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]);

1 Like

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

``````
function uniteUnique(arr) {
var newArr = arguments;
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]);

``````