New to JS. Doing a practice exercise in which I want to remove some specific items from an array and return the original array back without those items. I did it one way, but the sample solution was completely different and I want to try and understand it.
Is my line of thinking correct (see comments after each line of code below)? I think I understand, but I'm not sure if my reasoning is the correct reasoning or if I just lucked into it. I want to be sure I fully understand the next time I see something like this.
const pull = (arr, ...args) => {
// In this case, arr = arra1 and ...args = the values "a" and "c"
let argState = Array.isArray(args[0]) ? args[0] : args;
// I think this is saying, "Is the first item (index[0]) in arra1 included in the list of the arguments that follow (in this case, "a" and "c")?"
// The value of arra1[0] is "a", which is indeed one of the arguments that follow, so the ternary operator would return false and give you the "args", which are "a" and "c" in this case.
// "a" and "c" form an array (do they? I may be wrong here), so Array.isArray() would evaluate to true, and therefore argState = true
let pulled = arr.filter((v, i) => !argState.includes(v));
// I think this is saying, "Loop through arra1. v is the first value, "a" in this case. "Does argState contain the value "a"?
// It does, so it will come back true which will evaluate to false when we apply the "!". So "a" is NOT filtered into the new array called "pulled".
// Second loop, does argState contain the value "b"? It does not, so it will come back false, which will evaluate to true when we apply the "!". So "b" IS filtered into the new array called "pulled".
// And so on and so forth, and we would end up with "pulled = [ b , b ]" for this line.
arr.length = 0;
// I believe this just empties the original arr, or arra1 in this case. So arra1 = [ ]
pulled.forEach(v => arr.push(v));
// Now we loop through "pulled" and push each value onto arra1
return pulled;
// This will return the original arra1 with the new values [ b, b ]
};
let arra1 = ['a', 'b', 'c', 'a', 'b', 'c'];
console.log(pull(arra1, 'a', 'c')); // will return ["b","b"]
My main confusion stems from the !argState.includes(v)
part. If argState
in our previous line ended up with a value of true
or false
, it doesn't make sense to me that we can check if argState
includes a value (v)
from the arra1
array (i.e. "a", "b", or "c" in this exercise). How could argState
include values like this when it was already set to just the value true
or false
because of the Array.IsArray() check?
How could argState include values like this when it was already set to just the value true or false because of the Array.IsArray() check?
It's not set to true
or false
. It's set to an array:
let argState = Array.isArray(args[0]) ? args[0] : args;
If args[0]
is an array, it's set to that array. Otherwise, it's set to the whole args
array.
This is equivalent to
let argState;
if (Array.isArray(args[0])) {
argState = args[0];
} else {
argState = args;
}
This allows callers to use either the format
pull(someArr, ['foo', 'bar'])
or
pull(someArr, 'foo', 'bar')
and the use of the conditional operator to construct argState
then collects an array of ['foo', 'bar']
regardless of the format the caller used.