removeFromArrays - request for explanation of solution / learning tips?


#1

Hello!

I’ve been working through the Javascript Exercises and this one in particular completely stumped me. Even though the ReadMe file explicitly links to a page where the general concepts are explained, and I read this page (several times), I still was completely lost and had to view the solution.

A quick aside: I’m not sure if it’s just me but I feel at this point in the course there has been a big step up in difficulty and I don’t feel entirely prepared for it. I do all of the readings, but it’s difficult without more exercises to balance it out. I can read about something a million times and until I actually apply it in a meaningful way, the information is pretty close to useless (for me).

I found a lot of great resources for “args…” and array.filter but aside from cycling through some basic numbers, I couldn’t really find anything that made sense to me, personally, by applying it to something meaningful.

Here is the answer provided by the official solutions repo:

var removeFromArray = function(…args) {
const array = args[0]
return array.filter(val => !args.includes(val))
}

I was beginning to get the first line by the time I broke down and looked up the solution. It wasn’t clear to me in the documentation whether or not I needed to add an additional argument representing something else, or at least some brackets [] to denote the array.

The final line is also what gets me - I don’t understand “val” and another user pointed this out in this thread: Remove from Array

The above thread confirms that “val” is just a name for the elements of the array. Could in theory “val” be anything? Could I have called it ‘elementsOfArray’ or something? I think a few lessons ago we learned about naming variables in ways that make sense… hmmm :slight_smile:

I guess one of the parts that stumps me the most is the difference between “…args” and “val”. I mean, I know they’re different, but-- is “args…” a variable for the entire argument as a whole and then ‘val’ is a variable for just the items inside of the array?

expect(removeFromArray([1, 2, 3, 4], 3, 2)).toEqual([1, 4]);

It looks to me like that function is - is passing the right word? - six arguments.
So the array.filter filters through the elements of the array.
(I wish there were some arrow function exercises before introducing(?) them here, I guess).
Val is the elements of the array, so the function parameters.
The expression of the function is, I think, telling the function to return arguments not included in the “second half” of the above argument, being the “3, 2” number?

I’m not even sure of that but it would be my best guess.

If you guys know of any material that can go side-by-side with The Odin Project, I’d really appreciate it! I feel like this course is not enough (which of course I knew going into it, but I thought I could at least complete it and do other tutorials after, but since this is giving me so much trouble, I’d definitely be interested in some companion materials!)

Thanks! And apologies for the long post, I am an English major after all :slight_smile:


#2

I haven’t done that part of the course yet, (unless this is in the Web Dev 101 unit, though I don’t remember it from there), but this is interesting :slight_smile:

Args or arguments are things (variables, objects, sometimes even other functions in some languages) that are passed into something (a program, method, proc, etc.). I have a feeling you know this, but I restate it anyway, just in case.

You have a const called ‘array’ being set to args[0], which I am reading as the 1st item in the ‘…args’ passed into the ‘var removeFromArray’ function. In the example you give, this would be the array [1, 2, 3, 4], whereas the ’ 3, 2’ would be args[1] and args[2], respectively (the 2nd and 3rd arguments).

The filter thing I can’t really be sure of without doing the exercise / reading the course notes, but I just wanted to point out that when you say ““…second half” of the above argument, being the “3, 2” number?”, you seem to jump into the singular form, as if there is a single overarching ‘argument’. I think the removeFromArray function is designed to accept many arguments, not only the number of arguments (three) seen here, where the 1st argument must be an array, and all those following are values to be used in the filtering of that array.

It looks like your idea may well be correct; that the remaining args (those that are not arg[0]) are mapped against the array (arg[0]) and the filter then removes any matching values found from arg[0]. Any more detail on how I cannot really tell just from what you posted.

The devdocs linked in the last post to the thread you linked look interesting. I’m too tired to get deeper into this right now, but if I was in your shoes, I might go over those for a bit and see if it helped me understand the exercise / unit better (or sleep on it… that nearly always helps). A quick skim reading leads me to think ‘arrow functions’ might be a key JavaScript concept here (the bit with the ‘=>’ in it).

EDIT: I found this on arrow functions. Maybe it helps?


#3

So this line is giving you issues, which makes sense. It’s using an ES6 “Fat arrow function”, and they can be confusing. But if we expand it out into something a little more familiar:

let filteredArray = array.filter(function(memberOfArray){
  if(args.includes(memberOfArray) == true) {
    return false;
  } else {
    return true;
  }
})

return filteredArray;

As to args vs val, it’s a matter of where they’re being defined. As args is being defined as a parameter, using the spread operator, it is an array of all the values passed into the function. The first two lines (the function definition and the assignment to array) could also be written like this:

var removeFromArray = function(array, ...args){ ... }

This would create the variable array with the first parameter, and everything else would be assigned to another Array named args, because of the magic of the spread operator.

So when we run that array.filter(...), we pass into it a function that will be called for each member of array. What we choose to name the individual members of that array in our callback (where the short form used val, and in my expanded version I used memberOfArray) is completely up to us. Those aren’t reserved keywords or special in some way. It’s a good idea to use something that is meaningful, and that you won’t forget later, which is why I prefer the slightly longer name. :wink:

When the function in the filter runs, it returns one of two things: a falsy value (something that reads as false), or a truthy value (according to the MDN, ‘anything that doesn’t evaluate as falsy’). So if we say return true, we’re returning a truthy value. If we say return args.includes(memberOfArray), then whenever args includes the value memberOfArray we return true. So long as the return value evaluates to something true, the filter function will keep that particular member in the filtered array.

So the shorthand

 val => !args.includes(val)

is simply saying

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

Remember, the ! before the expression is the NOT sign – it inverts the value! So if args.includes(val) says “Yup, it’s in there! TRUE”, then the ! promptly FLIPS that to false, thus excluding only those members who are in the list of args.

Reading that back, I talk too much. Hope it helps, though.


#4

Neat. I enjoyed that explanation, Mr. SnowMonkey :wink:


#5

Thanks for asking this and for all your answers and explanations.
I’ve been stuck on this problem for a few days now and also felt like the reading thus far didn’t prepare me at all for this.

I could write the code to pass 1 or 2 tests, but not all 6 in the removeFromArray.spec.js file.

My solution was just getting more and more complex, so I knew it wasn’t right and googling made me even more confused.