6

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!

  • `forEach` will just iterate over the values `el = false` does not change the element in the array - you are just changing the local variable. It's the same as if you had done `let el = arr[i]` in your `for` loop and had used `el` throughout it. – VLAZ Sep 16 '19 at 11:52

7 Answers7

3

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);
DjaouadNM
  • 22,013
  • 4
  • 33
  • 55
3

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);
georg
  • 211,518
  • 52
  • 313
  • 390
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I'd personally prefer to use the array passed into the `forEach` callback - `(el, index, array) => array[index] = !el;` Sure, it's the same as `arr` but then the callback is self-contained and doesn't beak if `arr.forEach` is changed to, say, `myElements.forEach` – VLAZ Sep 16 '19 at 11:55
  • @VLAZ - Yeah, I mention to mention it was an option to do that. – T.J. Crowder Sep 16 '19 at 12:11
  • @georg - Thank you. Wow, my brain was really misfiring... :-) – T.J. Crowder Sep 16 '19 at 12:12
2

From your code, you're trying to change to el but the el variable that pass to callback function by forEach function I think it pass by value not pass by reference. From your question, Let's rewrite by using map function instead of forEach

const listOfBoolen = [false, true, false, true, true]
const newList = listOfBoolen.map(o => !o)
console.log(newList) // [true, false, true, false, false]
1

In the .forEach() version, a copy of the value in the array element is passed to the callback function. Changing that parameter value has no effect on the array element.

You could use .map(), but that would create a whole new array:

let newarr = arr.map(el => el == true ? false : true);

Your original for loop is also fine.

Pointy
  • 405,095
  • 59
  • 585
  • 614
1

You should modify the array element by index:

let arr = [true, false, true, false, true]
arr.forEach((el, i, a) => el === true ? a[i] = false : a[i] = true);
console.log(arr);
//OR: Simply
//arr.forEach((el, i, a) => a[i] = !el);
Mamun
  • 66,969
  • 9
  • 47
  • 59
1

you are not assigning the value to arry. you cam use map() and foreach to do this, like given below

arr = [true, false, true, false, true];
arr =arr.map(val=> this.val=!val);
console.log(arr)

///////////////////////////////////

arr = [true, false, true, false, true];
arr.forEach((val,key)=>arr[key]=!val);
console.log(arr)
Zulqarnain Jalil
  • 1,679
  • 16
  • 26
0

You are changing the value of the parameter supplied in the forEach() callback, but not actually updating the array.

  1. You need to either modify the original array using forEach() by assigning the new value to the index. Comparing the boolean with false will invert it as if the value is false then false === false would be true and if it is true then true === false would be false.

  2. Use map and invert the values and get a new array from the inverted values. I used the XOR ^ to invert the boolean, but the usual !boolean is a better alternative than this.

let arr = [true, false, true, false, true]; 

// Creates a new array and applying xor ^ to inverse the boolean
const inverted = arr.map(el => Boolean(1 ^ el));
console.log(inverted)

// Modifies original array
arr.forEach((el, idx, a) => a[idx] = el === false);
console.log(arr)
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44