Littlee
Littlee

Reputation: 4337

Manipulate previous item inside Array.map?

I'm transforming my array with Array.prototype.map(), and if the current item matches some conditions, I want to change its previous item.

The code below seems not working, how do I do it without a for loop?

var nums = [1, 2, 3, 4, 5];

var res = nums.map((item, index, array) => {
  if (item > 3) {
    array[index - 1] += 1;
  }
  return item;
});

console.log(res); // [ 1, 2, 3, 4, 5 ], I want [1, 2, 4, 5, 5]

Upvotes: 2

Views: 2381

Answers (5)

user3297291
user3297291

Reputation: 23372

Disclaimer: this answer is only here because I feel whenever somebody asks "how do I do X without a for loop", I feel there should at least be one recursive solution between all the maps and reduces :)

how do I do it without a for loop?

If you don't care much about performance or the risk of blowing the stack, you can go with a recursive function!

Here's an example:

  • Destructure your array into first, second and the rest
  • If first is empty, we've reached the end of our computation and return the result
  • If first is not empty, we can compare it to second to determine its value. We add the value to our result and recurse:
  • Call the function again, but now with [second, ...rest] and passing along our result

const input = [ 1, 2, 3, 4, 5 ];
const Empty = Symbol();

const incIfBt3 = 
  ([first = Empty, second, ...rest], result = []) =>
    first === Empty
      ? result
      : incIfBt3(
          [second, ...rest],
          [...result, first + (second > 3)]
        );
        
        
console.log(incIfBt3(input));

Upvotes: 1

KooiInc
KooiInc

Reputation: 122956

You can use a reducer

var res = [1, 2, 3, 4, 5]
  .reduce((reduced, item, i) => {
     i && (reduced[i-1] += item > 3 ? 1 : 0);
     return [...reduced, item];
   }, []);

console.log(res); 

Upvotes: 2

JLRishe
JLRishe

Reputation: 101738

Instead of trying to change the previous item, you can use the array parameter to look at the next item and return a value for the current item accordingly:

var nums = [1, 2, 3, 4, 5];

var res = nums.map((item, index, array) => item + (array[index + 1] > 3 ? 1 : 0));

console.log(res); // [1, 2, 4, 5, 5]

You can also take advantage of the fact that the numeric value of a boolean is either 1 or 0 to eliminate the conditional expression:

var nums = [1, 2, 3, 4, 5];

var res = nums.map((item, index, array) => item + (array[index + 1] > 3));

console.log(res); // [1, 2, 4, 5, 5]

Upvotes: 0

JanS
JanS

Reputation: 2075

You can look ahead instead of trying to look behind:

var nums = [1, 2, 3, 4, 5];

var res = nums.map((item, index, array) => {
  if (array[index + 1] > 3) {
    item += 1;
  }
  return item;
});

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 371049

Arrays that are in the process of being created from .map can't be referenced like that. Instead, create the array outside of the forEach, and push to / assign to it:

var nums = [1, 2, 3, 4, 5];
const newArr = [];
nums.forEach((item, index) => {
  if (item > 3) newArr[index - 1] += 1;
  newArr.push(item);
});

console.log(newArr); // I want [1, 2, 4, 5, 5]

Upvotes: 1

Related Questions