Beat mix invert function

Hi there,

Hi there,

I am currently working on the beat mix project and had a question about the ‘invert’ function, which should take an array of boolean values and switch them to their inverse value. Having looked at the solution to this I can see that they use a for loop, looping through each element of the given array and switching it to its inverse value:

for (let i = 0; i < drums.length; i++) {
    drums[i] = !drums[i];
  }

I had originally been attempting to do this using the .forEach() method but was having errors thrown up in the testing that it was not switching the values.

drums.forEach(element=>
    element=!element)

What is different between these two bits of code and why does this .forEach() method not cause an inversion of the values?

Cheers

Hi!

First of all, I have to say I’m fairly new to JavaScript myself, so no guarantee that this is the correct explanation, but maybe it helps.

I guess It’s because in the .forEach, you’re doing nothing of consequence to each element. It’s true that it takes every element of drums and inverts it, but as soon as this is done, it’s forgotten.
In the for-loop, however, you assign each index anew, thereby mutate the drums array.

If you wanted to make .forEach work for this particular example, you’d have to use a fresh array, like so:

drums = [true, true, false, true, false];
drumsCopy = [];

drums.forEach(element=> {
  element=!element
  drumsCopy.push(element)
})

Cheers

1 Like

Thanks for the reply.

I was under the impression that the callback function within .forEach() could mutate an array if programmed to do so.

I would therefore have thought that element=!element would have mutated the array. I understand that .forEach always returns undefined but should the callback function not be enacted on each array element?

From the MDN documentation :
forEach() does not mutate the array on which it is called. (However, callback may do so)

Still a little confused

so I think I maybe understand now, possibly, maybe, probably not.

Array1=[true,false,false]

Array1.forEach((element, index, array)=> {
    element=!element
    array[index]=element
})
console.log(Array1)

this outputs [false, true, true]

There you go, that’s the improved solution I wanted to post, after reading your first reply. This way, the callback function does mutate the array, even though forEach does not.

Like I said, I’m a newbie, too, but I’d think that this is the most elegant way to achieve what you wanted to do while using .forEach

However, it goes even easier when using .map():

console.log(drums.map(element => element = !element)

This does exactly what you wanted to do since it inherently creates a new array.