While I finally managed to solve the Falsy Bouncer challenge (using a different approach), I’m not sure why my original approach didn’t work.
I’d be most grateful for any insights into why this approach doesn’t work. Is there a way to make this work? Thanks in advance.
This is the code from my original approach:
function bouncer(arr) {
let copyOfArray = arr;
let result = [];
for (let i = 0; i < copyOfArray.length; i++) {
if (copyOfArray[i] === false || copyOfArray[i] === null || copyOfArray[i] === 0 || copyOfArray[i] === "" || copyOfArray[i] === undefined || copyOfArray[i] === NaN) {
// This should remove 1 element at index "i".
copyOfArray.splice(i, 1);
}
}
console.log(copyOfArray);
console.log(arr);
return copyOfArray;
}
bouncer([7, "ate", "", false, 9]);
I thought ideally if this approach could be made to work, then I could keep it simple without having to use a different built-in method – which I did eventually have to use – to solve the challenge. (I won’t talk about the different method here to avoid spoiling it for others)
Regarding the first thing you pointed out copyOfArray[i] === NaN → I had no idea it will never evaluate to true, that’s very helpful, thanks.
Regarding the second point copyOfArray.splice(i, 1) → this is very interesting, it never occurred to me that I am skipping over some elements.
I’m still a bit confused about this and this is what I think is happening.
We call bouncer([7, "ate", "", false, 9])
We loop through the values in the array. By the time when i = 2, since
copyOfArray[i] === ""
We then execute:
copyOfArray.splice(i, 1);
This removes what’s in index 2 of the array, namely “”.
The array now looks like this:
[7, "ate", false, 9]
We now iterate through the loop again and this time i = 3. Since we had deleted what was in index 2, now what’s in index 3 is actually the number 9. So in effect, the “for” loop never looked at the value false (which is now in index 2), as we basically skipped it.
I’d be most grateful if you could let me know whether that’s an accurate assessment, thanks in advance.
As for the following:
let copyOfArray = arr
I had no idea that doesn’t create a copy of arr. I just looked up how to clone an array and it looks like JavaScript gives you so many different ways of doing so… it’s pretty confusing… – I need to look into this a bit more.
Array cloning is something which I found more interesting than is probably healthy
You will most likely come across this again when you complete later challenges in this course.
Here is an instructive FCC article about shallow copies v true cloning of arrays in Javascript.
In essence, there are many methods which can create shallow copies of arrays, which means that if an array is multi-dimensional, the deeper levels will be references to the original only and thus could mutate the original. The only method I know of which creates a complete clone and avoids mutation altogether is:
Keeping in mind the cloning and splice stuff, this is why you should generally tackle these problems from the opposite direction for filtering. Instead of creating a copy and removing items you don’t want, you should create a new array and only insert what you need.
For reference I’ll show how to keep only even numbers from an array of numbers nums using three functionally equivalent methods. In my opinion, each method is successively easier to understand than the previous.
function copyAndRemovalFilter(nums) {
const result = Array.from(nums);
for (let i = 0; i < result.length; i++) {
if (result[i] % 2 !== 0) {
result.splice(i, 1);
i--;
}
}
return result;
}
function buildUpFilter(nums) {
const result = [];
for (const num of nums) {
if (num % 2 === 0) {
result.push(num);
}
}
return result;
}
function justUseTheBuiltinFilter(nums) {
return nums.filter((num) => num % 2 === 0);
}
@colinthornton , wow this is really insightful, really interesting stuff, thanks!
The solution I did use to solve the challenge is with the .filter built-in method. I had to do a google search to learn about this method.
I think the second solution you shared (ie using the .push method) is really interesting. In a way I prefer it because if I had thought of this approach, I may have been able to solve the challenge using what I already knew, without having to search online for a built-in method.
Thanks again. In the future, I’ll know I can approach these types of problems in these two ways. (I don’t think I’ll use the .splice method given that it can lead to problems as @camperextraordinaire pointed out, although you did show that it can be made to work).