Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's wrong with my forEach method when a simple For Loop works just fine

So, I have a simple task, given the array: let arr = [true, false, true, false, true]; I need to reverse true to false and visa versa. I have managed to do this with a for loop: And it works fine.

Now, I'm trying to do the same with a forEach and I can't figure out why this won't work. So, here's my code:

for (let i = 0; i < arr.length; i++) {
    if (arr[i] === true) arr[i] = false;
    else arr[i] = true;
} // it works

// for some reason, this doesn't
arr2.forEach(el => el === true ? el = false : el = true);
console.log(arr)

//Neither this: 
arr.forEach(el => el === true && el = false || el === false && el = true);
console.log(arr)

The map doesn't work either: Can someone point out my mistake and explain what I am doing wrong? Maybe show other ways to solve it? With filter, reduce or which is more preferrable? A one-liner solution is highly preferred. Thank you for your answers!

like image 232
Andrey Bondarev Avatar asked Sep 16 '19 11:09

Andrey Bondarev


People also ask

Why is my forEach not working?

The "forEach is not a function" error occurs when we call the forEach() method on a value that is not of type array, Map , or Set . To solve the error, make sure to only call the forEach method on arrays, Map or Set objects. Copied!

Is forEach more efficient than for loop?

for loops are much more efficient. It is a looping construct specifically designed to iterate while a condition is true, at the same time offering a stepping mechanism (generally to increase the iterator).

When should we not use forEach?

Even though using return inside the callback of a forEach() loop would halt execution for the current iteration and move on to the next item in the loop, you should not use it to mimic the functionality of continue .


2 Answers

What you need is Array.prototype.map, because assigning el is not like assigning arr[i] (it doesn't mutate the array):

arr2 = arr2.map(el => el === true ? false : true);

Which can be simplified to just:

arr2 = arr2.map(el => !el);
like image 182
MrGeek Avatar answered Oct 23 '22 10:10

MrGeek


You're assigning to el, which is the parameter to your callback. That has no effect whatsoever on the value in the array. The value of the array element is copied to el, after which there is no link between the array element and the el parameter. It's like this:

function example(el) {
  console.log("before", el);
  el = 42;
  console.log("after", el);
}

let a = [1];
console.log("a before", String(a));
example(a[0]);
console.log("a after", String(a));

If you want to assign to the array from within a forEach, you have to do it by index:

arr.forEach((el, index) => el === true ? arr[index] = false : arr[index] = true);

(I strongly recommend not abusing the conditional operator that way, but that would be the nearest to what you're trying to do.)

The more idiomatic thing to do would be to use map, and ! rather than the conditional operator:

const newArray = arr.map(el => !el);
like image 25
T.J. Crowder Avatar answered Oct 23 '22 10:10

T.J. Crowder