How to convert arguments to arrays? Help with "Seek and Destroy" algorithm challenge

I’m trying to solve the “Seek and Destroy” algorithm challenge by reading up on fCC’s guide to arguments. I’m trying to run the code they provide on turning arguments into arrays but my console outputs getGrades is not defined. Do you know why?

I’m having some trouble understanding converting arguments into arrays in general. In this challenge, are we supposed to create a separate array for both the 2 and 3 arguments…?

Link to challenge: https://www.freecodecamp.org/challenges/seek-and-destroy

Link to arguments guide:

Code from guide that won’t pass:

function getGrades() {
    var args = Array.prototype.slice.call(arguments, 1, 3);
    return args;
}

// Let's output this!
console.log(getGrades(90, 100, 75, 40, 89, 95));

OK, having reread the challenge…

are we supposed to create a separate array for both the 2 and 3 arguments…?

The challenge says,

You will be provided with an initial array (the first argument in the destroyer function), followed by one or more arguments

So, there will always be a first argument, and then at least one other argument. So, that means that you will get at least two argument, but maybe three, four, our fifty-seven. You can’t have separate handlers for each.

The array is easy to get - you just declare it in your function declaration like normal:

function destroyer(arr) {

It is always the first argument so that array will fall into arr, like normal.

The problem is all the other items. There will be at least one and maybe thousands. Putting them in an array sounds like a good idea. You experimented with:

Array.prototype.slice.call(arguments, 1, 3);

That is a good start. (Although I found Array.from(arguments).slice(... a little more direct.) But why include the parameter 3? That is telling it to stop at the third element. The first parameter in `slice’ (1) tells it to start at the first element and the second parameter (3) tells it to stop at the third. But you don’t want it to stop - you want it to keep going until you get to the last one. If you omit the second parameter, it will just keep going until the end, which is what you want. I think it is that 3 that is screwing you up. That makes it only work for two parameters.

Is that clear?

2 Likes

typically we would see function(x,y,z) eg paramater for each argument but you can also just use one eg function(x) … then if you console.log(arguments) you get whatever you passed in for x …arguments is a special word it covers all parameters passed so it has a length eg arguments.length() and you can do arguments[0] etc
so if you passed allarguments([1,2],4,6) from a function created like function allarguments(params) and did then console.log(arguments[0]) you would get [1,2] if you did console.log(arguments[1]) you would get 4 etc etc .
so in destroyer it wants you to check the array passed eg [1,2,3,1,2,3] which in this case would be arguments[0] and filter this array and return only those numbers that do not appear in rest of arguments eg 2,3 … so if you could put 2,3 into another array you could compare the arguments[0] array against this array so from arguments.length 1 on wards you put into an array … how do you put them into an array … well create an array and use a for loop to loop through arguments and push to array … then all you have to do is filter one array and check against another …

A little clearer, though I’m still a bit confused about how the filter method and arguments object work.

I took a look at the intermediate solution, for example:

function destroyer(arr) {
	
  var args = Array.from(arguments).slice(1);
  return arr.filter(function(val) {
  return !args.includes(val);  
  });


}

destroyer([2, 2, 3, 1, 2, 3], 2, 3);

Some questions:

  1. var args = Array.from(arguments).slice(1);
    What confuses me about this is how Array and arguments aren’t explicitly defined anywhere in the code. My basic understanding of that is because Array.from is a method that just creates a new array. Arguments is a local variable that all functions can take on. My question is: how does Array.from(arguments) know I’m referring to the destroyer function without explicitly referencing it?

  2. I’m confused about the parameter passed into the callback function of filter. Does val refer to the values passed in for arr? Again, since it’s not explicitly defined, I have trouble seeing the relationship.

  3. return !args.includes(val);
    Does this mean: return arguments passed in for val that are not included in args? This was my first time seeing the ! operator used.

I withdrew my post because I understand now :smiley: !!

1 Like

Just to make sure we understand because these are important, complex subjects and others may be reading.

  1. Array is declared in the programming language. It has methods (functions) attached to it, including .from and .slice. Normally you don’t have to deal with something like Array directly because you can just apply it to something is already an array. But arguments is not an array, so we access that function to convert it’s iterable data into an array with Array.from. The output from that is an array, so the slice method can be chained onto. But it could have broken into two steps.
var args = Array.from(arguments);
args = args.slice(1);

But it’s common to chain them one after the other.

The object arguments is not declared by you but is created when you called the function. Most of the time, we don’t need to access it directly, but here we do.

  1. The variable val is a name we’ve chosen. The filter function will step through each value in the array, and each value will be passed into the callback function as val, passed one at a time. But we could have called it anything.

  2. The method filter will go through every value that is passed to it and if you return true from the callback function, then that value will be included in the final array returned from filter. The statement args.includes(val); will return true if val is in args. But that is the opposite of what we want. So !args.includes(val) tells it to return true (include this value in our final array) if this value is not in the args array. So:

arr.filter(function(val) {
  return !args.includes(val);  
});

will return an array of the arr values that are not in the args array. This is what we want so we return it from the function destroyer. But this also could have been two steps.

I would suggest being strict about your indenting to make things clearer:

function destroyer(arr) {
	
  var args = Array.from(arguments).slice(1);
  return arr.filter(function(val) {
    return !args.includes(val);  
  });
}

destroyer([2, 2, 3, 1, 2, 3], 2, 3);

Develop good formatting habits now or things will be a nightmare later.

1 Like