Help needed in sorted union algorithm challenge!

Here is my Code:


function uniteUnique(arr) {
 var a=arr.concat(arguments[1],arguments[2]);
 
  function onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
}
var unique = a.filter( onlyUnique ); 
  return unique;
}
uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]); 



i am getting the results correct for the arr having 3 arguments. But it is not giving correct results for less than or more than 3 arguments. What to do in that case for accessing arguments not equal to 3?

1 Like

Urgh…Sorted Union

True story, this is what sits at the top of my actual submission:

// Dear Quincy or other code reviewer,
// I finished this and then read the wiki solution. 
// I recognize that this hamfisted solution would break 
// if you threw more arguments at it, and in a deployed 
// app this would not scale...but my head hurts; I have a toddler.
// Be reasonable! I'm still avoiding Where Art Thou. You are masochists.
// Love you guys. Thanks for FCC. 
// Kisses, Jackson x
// p.s. Enjoy the spaghetti code below. Yum!

My ‘solution’ is [here](https://www.freecodecamp.com/challenges/sorted-union#?solution=%2F%2F%20Dear%20Quincy%20or%20other%20code%20reviewer%2C %2F%2F%20I%20finished%20this%20and%20then%20read%20the%20wiki%20solution.%20 %2F%2F%20I%20recognize%20that%20this%20hamfisted%20solution%20would%20break%20 %2F%2F%20if%20you%20threw%20more%20arguments%20at%20it%2C%20and%20in%20a%20deployed%20 %2F%2F%20app%20this%20would%20not%20scale...but%20my%20head%20hurts%3B%20I%20have%20a%20toddler. %2F%2F%20Be%20reasonable!%20I’m%20still%20avoiding%20Where%20Art%20Thou.%20You%20are%20masochists. %2F%2F%20Love%20you%20guys.%20Thanks%20for%20FCC.%20 %2F%2F%20Kisses%2C%20Jackson%20x %2F%2F%20p.s.%20Enjoy%20the%20spaghetti%20code%20below.%20Yum! function%20uniteUnique(args)%20{ %20%20 %20%20var%20arr%20%3D%20[]%3B %20%20for%20(var%20i%20%3D%200%3B%20i%20<%20arguments.length%3B%20i%2B%2B)%20{ %20%20%20%20arr.push(arguments[i])%3B %20%20} %20%20 %20%20%2F%2F%20~%24%26~MOM’S%20SPAGHETTI~%26%24~%20%2F%2F %20%20 %20%20for%20(var%20j%20%3D%20arr.length%20-%201%3B%20j%20>%200%3B%20j--)%20{ %20%20%20%20for%20(var%20k%20%3D%20arr[j].length%20-%201%3B%20k%20>%20-1%3B%20k--)%20{ %20%20%20%20%20%20if%20(arr[j-1].includes(arr[j][k]))%20%7B%0A%20%20%20%20%20%20%20%20console.log(%22removed%20%22%20%2B%20arr%5Bj%5D%5Bk%5D%20%2B%20%22%20from%20%22%20%2B%20arr%5Bj%5D)%3B%0A%20%20%20%20%20%20%20%20arr%5Bj%5D.splice(k%2C%201)%3B%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20if%20(arr%5Bj-2%5D)%20%7B%0A%20%20%20%20%20%20%20%20if%20(arr%5Bj-2%5D.includes(arr%5Bj%5D%5Bk%5D))%20%7B%0A%20%20%20%20%20%20%20%20%20%20arr%5Bj%5D.splice(k%2C%201)%3B%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%0A%20%20%2F%2F%20END%20SPAGHETTI%20%2F%2F%20%0A%20%20%0A%20%20var%20flat%20%3D%20%5B%5D.concat.apply(%5B%5D%2Carr)%3B%0A%20%20%0A%20%20return%20flat%3B%0A%20%20%0A%7D%0A%0AuniteUnique(%5B1%2C%203%2C%202%5D%2C%20%5B1%2C%20%5B5%5D%5D%2C%20%5B2%2C%20%5B4%5D%5D)%3B%0A). But as stated in my comments, I really only managed to knock something together that passes the given tests and I had the same issue with various numbers of arguments that you do…

I hope you get a detailed good answer, because I could use it :wink:

Here is my new solution. It will pass the given test but not any other. I dont think its worth it.


function uniteUnique(arr) {
  var a=arr.concat(arguments[1],arguments[2]);

  if(arguments.length==2){
     var a=arr.concat(arguments[1]);
  }
  if(arguments.length==4){
     var a=arr.concat(arguments[1],arguments[2],arguments[3]);

  }
 
  function onlyUnique(value, index, self) { 
    return self.indexOf(value) === index;
}
var unique = a.filter( onlyUnique ); 
  return unique;
}
uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]); 



This is my solution. Has a loop-in-a-loop I want to get rid of. I haven’t submitted a second one yet, but I think this works for at least two arguments.


function uniteUnique(arr) {
  var args = Array.from(arguments);
  var united = [];
  for (var i = 0; i < args.length; i++) {
    for (var j = 0; j < args[i].length; j++) {
      if (!united.includes(args[i][j])) {
        united.push(args[i][j]);
      }
    }
  }
  return united;
}
2 Likes

I went back and fixed mine so that it would stand up to test cases with more args than those presented.

I was surprised that it only took me about 10 minutes or so to solve from a clean slate this time, because the first time took me a couple of days!

It’s nowhere near as concise as @P1xt’s solution, but it’s an honest-to-goodness improvement on my previous shambles :slight_smile:

Spoiler
/*jshint esnext: true */

function uniteUnique(arr) {
  
  // create array of arguments
  let arrays = [];
  for (let args of arguments) {
    arrays.push(args);
  }
  
  // concatenate arrays into newArr
  let newArr = [];
  for (let arraysIndex = 0; arraysIndex < arrays.length; arraysIndex++) {
    for (let innerArrayIndex = 0; innerArrayIndex < arrays[arraysIndex].length; innerArrayIndex++) {
      newArr.push(arrays[arraysIndex][innerArrayIndex]);
    }
  }
  
  // Remove dupes, starting at the end of the array
  for (let j = newArr.length -1; j > 0; j--) {
    if (newArr.indexOf(newArr[j]) !== j) {
      newArr.splice(j, 1);
    }
  }
  
  return newArr;
}

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

yours is better than mine.

ShwetaRajput
This was already pointed out, but you can turn a variable number of arguments passed to a function into an array using:
var args = Array.prototype.slice.call(arguments);
This trick helps to turn the array-like Arguments object into an actual array.
The args array can be then be used for the reduced function to solve the challenge.

1 Like

i want to post my code. can someone point me towards the ‘how-to’ so I can do that?

thanks.

function uniteUnique(testArray) {
arr=Array.prototype.slice.call(arguments);
var flat=flattenArray(arr);
console.log(flat);
allUnique(flat);
console.log(flat);
return flat;
}
function flattenArray(arr) {
//var flattened=[];
return arr.reduce(function(acc, item) {
//debugger;
if (Array.isArray(item)) {
// console.log(acc,item);
return acc.concat(flattenArray(item));
}
return acc.concat(item);
}, []);
}
function allUnique (arr) {
for (i=0; i< arr.length; i++) {
// for (j=0; j<testArr.length; j++) {
if (arr.indexOf(arr[i], i+1)>0) {
var leftSide=arr.indexOf(arr[i],i+1);
console.log(arr.indexOf(arr[i],i+1));
var fixedArr=arr.splice(leftSide,1) ;

        console.log(arr);
      //  console.log(arr);
        allUnique(arr);
    }
}

}
//var test=[[1, 3, 2], [5, 2, 1, 4], [2, 1]];
uniteUnique([1,1]);

so with all that code above, I wanted to say that apparently my 'flattenArray function apparently goes too far in that it goes til there is no where else to go. so for this test:
uniteUnique([1, 3, 2], [1, [5]], [2, [4]]) should return [1, 3, 2, [5], [4]]

I get the following results:

[1,3,2,5,4]

which is correct except for all the extra brackets.

I’m actually not sure why my answer is incorrect so if someone could help me there, I’d appreciate it.

Secondly, I read above about testing arguments of less than two, and my solution above yields what certainly looks like correct results.

@gobees, I missed this post initially, sorry for the delay:

http://forum.freecodecamp.com/t/forum-code-formatting/25574?u=jacksonbates

This is a lot along the lines that i was hoping to do! I was having the weirdest issue trying to figure out how to access multilevel arrays, I must have forgotten since it’s been so long. Also was having issues trying to set the limit on my second loop properly, settings it to arr[i] is exactly what I need!

js
function uniteUnique(arr) {
  // concat array
  var args = Array.from(arguments);
  var merged = [].concat.apply([], args);
  //reduce array 
  uniqueArray = [];
  var i = 0;
  while (i < merged.length) {
    if(uniqueArray.indexOf(merged[i]) < 0) {
      uniqueArray.push(merged[i]);
    }
    i++;
  }
  return uniqueArray;
}

Here’s my solution. I found the reduction of the concatenated array really hurt my brain on this one. Tried reduce() and filter() and got nowhere in the end just used a loop.

So, I read through this thread and thought I would post my code. It’s probably not as efficient as others posted above, but I feel like what I’ve done is comparatively much more simple minded.

Or possibly, it’s simply that my way of thinking about these things appears intuitive to me just because it’s my way of thinking. But looking at everyone else’s code, I feel like yours all seem very complicated to me, using methods and syntax, etc. that I don’t even recognize.


function uniteUnique(arr) {
var all = [] ;
var end = []  ;
for (i=0; i<arguments.length; i++){
  while (arguments[i].length>0){
    all.push(arguments[i].shift());
  }
} //puts everything into one array

  while (all.length>0){
   var check = all.pop();
 if (all.includes(check) === false){  //now that I look at it, could be (!all.includes(check))
  end.unshift(check);
 }
  }
  return end;
}

This also works:

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

you can grab all the arguments with …arr

Slightly modified:

function sortedUnion(...args){
	return args.reduce((arr1, arr2) => 
	arr1.concat(arr2.filter(num => !arr1.includes(num))));
}
2 Likes

One more time, you show the forums and myself the golden ticket. @P1xt is my favorite.

My solution:

function uniteUnique( ...arr ) {
	let newArr = [].concat( ...arr );
	let newArrL = newArr.length;

	for( let k = 0; k < newArrL; k++ ) {
		for( let x = k; x < newArrL; x++  ) {
			if( newArr[k] == newArr[x+1] ) {
				newArr.splice( x+1, 1 );
			}
		}
	}
	
	return newArr;
};

console.log( uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]) ); //[1, 3, 2, 5, 4]
console.log( uniteUnique([1, 3, 2], [1, [5]], [2, [4]]) ); //[1, 3, 2, [5], [4]]
console.log( uniteUnique([1, 2, 3], [5, 2, 1]) ); //[1, 2, 3, 5]
console.log( uniteUnique([1, 2, 3], [5, 2, 1, 4], [2, 1], [6, 7, 8]) ); //[1, 2, 3, 5, 4, 6, 7, 8]

U can try this:

var newArr=[];
for(let i=0;i<arguments.length;i++){
newArr=newArr.concat(arguments[i]);
}