freeCodeCamp Challenge Guide: Sorted Union

Here is my solution. I like it because of basic procedural for loop and long line of functional chain of methods. Yet it is pretty short though have no idea if it is most performance-efficient. Would appreciate wise advise/critique.

    function uniteUnique2() {
        var arrs = Array.from(arguments), flattened = [];
        for (var i = 0; i < arrs.length; i++) {
            flattened = flattened.concat(arrs[i].filter(function(elt) {
                return flattened.indexOf(elt) === -1;
            }));
        }
        return flattened;
    }

Really interesting to see everyone’s solutions! Here’s my 2 cents worth:

function uniteUnique(arr) {
  var array = Array.from(arguments);
  var merged = [].concat.apply([], array);
  var newArray = [];

  for (i=0; i<merged.length; i++) {
     if (merged.indexOf(merged[i])=== i) {
       newArray.push(merged[i]);
     }
  }
  return newArray;

}

1 Like

4 ways to do it :slight_smile:

#1

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

#2

function uniteUnique2() {
  // step 1, convert arguments to array of arrays
  var args = Array.from(arguments);

  // step 2, flatten arrays into 1 array
  var arr = args.reduce((a, b) => a.concat(b));

  // step 3, filter unique values using indexOf to match first ocurrence, discard others
  return arr.filter((v, i, a) => i === a.indexOf(v));  
}

#3

function uniteUnique3() {
  return Array.from(arguments).reduce((a, c) => a.concat(c.filter(v => a.indexOf(v) == -1)),[]);
}

#4

// one liner using spread operator
function uniteUnique4(...arr) {
  return arr.reduce((a, c) => a.concat(c.filter(v => a.indexOf(v) == -1)),[]);
}
2 Likes

I made two solutions since I solved it first with a nested loop and was eager to try to solve it with reduce as well.

// first solution using a nested loop
function uniteUnique(arr) {
    var sumArr = [];
    for (var i = 0; i < arguments.length; i++) {
        var argArr = arguments[i];
        for (var k = 0; k < argArr.length; k++) {
            if(!sumArr.includes(argArr[k])) {
                sumArr.push(argArr[k]);
            }    
        }
    }
    return sumArr;
}

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


// second solution using reduce
function uniteUnique(arr) {
    var sumArr = [];
    for (var i = 0; i < arguments.length; i++) {
        sumArr = sumArr.concat(arguments[i]);
    }
    
    var uniqArr = sumArr.reduce(function(a, b) {
        if (a.indexOf(b) < 0) {
            a.push(b);
        }
        return a;
    },[]);
    
    return uniqArr;
}

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

@AAdevelop i think you meant to post this in Convert HTML Entities. This is Sorted Union, which is the next one on the list. Thought you might want to know.

  • i liked the Set method using ES6 but I couldn’t get the editor to let me use it.
    • *Sets can only have unique values
  • first thing i do is use the spread operator to get the arguments into an array
  • then i use a for loop and reduce and concat to flatten the arrays into one
    • it preserves the values that were themselves in a mini array of one so that’s good
  • then i make yet another array and use reduce again
  • basically using indexOf(). it returns -1 if item isn’t there so as it reduces the first occurrence of a value gets pushed in
  • then the second occurrence comes along and now the index is positive so it doesn’t get pushed
  • this challenge is cool you have to use a lot of methods and reduce can really do some cool things when paired with some simple methods
1 Like

Short, but sweet one liner

function uniteUnique(arr) {
  return [...new Set([].concat(...arguments))];
}
15 Likes

My attempt using reduce and a for loop:

function uniteUnique(arr) {
  var args = [].slice.call(arguments);
  return args.reduce(function(a,b){
    for (var i = 0; i < b.length; i++) {
      if(a.indexOf(b[i]) !== -1) {
        b.splice(i, 1);
        i--;
      }
    }
    return a.concat(b);
  });
}

I was very surpised that it worked, but it worked :smiley:

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

}

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

function uniteUnique(arr) {
var args = [];
var test = [];
var answer = [];
for (var i = 0; i<arguments.length; i++) {
args.push(arguments[i]);
}
for (var j = 0; j<args.length; j++) {
for (var k = 0; k<args[j].length; k++){
test.push(args[j][k]);
}
}
answer = test.filter(function(item, pos) {
return test.indexOf(item) == pos;
}
);
return answer;
}

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

Hi All,
Just another solution:

[code]function uniteUnique() {
var arr = [];
var combinedArray = [];
for ( var x in arguments){
arr = arr.concat(arguments[x]);
} for ( var i in arr )
{
if (arr.indexOf(arr[i]) == i)
{
combinedArray.push(arr[i]);
continue;
}
}
return combinedArray;
}

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

The advanced solution is soooooooooo smart! Slightly increasing the efficiency by making the segmentedly incremental search in the intermediate solution into a continuous one!

function uniteUnique(arr) {
  
  // Receive (n) arguments
  var args = Array.prototype.slice.call(arguments);
  
  // Converted arguments in array
  var flattened = args.reduce(function(a, b) {
return a.concat(b);
  }, []);
  
  
  // Remove repeated elements
  var newarr = flattened.filter(function(a, i) {
return flattened.indexOf(a) == i;
  });
  
  return newarr;
  
}

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

Hello !

Here’s my code based partially on ES6. Didn’t see something like this here:

function uniteUnique(arr) {
  
  var args = [].slice.call(arguments),
      origin = args[0],
      secArgs = [],
      unique = [];
  
  if(args.length === 2)
    secArgs.push(args[1]);
  else if(args.length === 3)
    secArgs.push(args[1], args[2]);
  else if(args.length === 4)
    secArgs.push(args[1], args[2], args[3]);
  
  unique = secArgs.reduce(function(a,b) {
    return a.concat(b);
  });

  return origin.concat(unique.filter(items => !origin.includes(items)));
}
uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]);

Cheerio!

The intermediate solution doesn’t work if some of the sub-arrays have repeating numbers.

using this:

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

we get this:

arrA: 1,1,2 arrB: 5,2,2,4 i: 5 arrA.indexOf(i): -1
arrA: 1,1,2 arrB: 5,2,2,4 i: 2 arrA.indexOf(i): 2
arrA: 1,1,2 arrB: 5,2,2,4 i: 2 arrA.indexOf(i): 2
arrA: 1,1,2 arrB: 5,2,2,4 i: 4 arrA.indexOf(i): -1
arrA: 1,1,2,5,4 arrB: 2,1 i: 2 arrA.indexOf(i): 2
arrA: 1,1,2,5,4 arrB: 2,1 i: 1 arrA.indexOf(i): 0
=> [ 1, 1, 2, 5, 4 ]

Is there a solution to this using array.filter?

1 Like

Here is my solution:

function uniteUnique(arr) {
	var args = [].slice.call(arguments);
	var result = [];
	
	function reducer(acc, cur, index, arr) {
		cur.forEach(function(elem){
			if(result.indexOf(elem) === -1) {
				return result.push(elem);
			}
		});
	}
	
	args.reduce(reducer, []);
	return result;
}

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

My solution:

function uniteUnique(arr) {
  arr = [].concat(...arguments);
  
  arr = arr.filter((item, pos, self) => {
    return self.indexOf(item) == pos;
  });
  
  return arr;
}

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

//AGGH!! Why doesnt this work, It returns the right answers but doesn pass the test!

function uniteUnique(arr) {
  arr = [];
  for(var i=0;i<arguments.length; i++){
  var temp = arguments[i];

  for(var j=0; j<temp.length; j++){
      if(arr.indexOf(temp[j]) < 0){
      arr.push(temp[j]);
     }
   }

 }
 return arr;  
}

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