Home > Software engineering >  Does the Array.prototype.forEach() method allow the skipping of iterations by modifying the index pa
Does the Array.prototype.forEach() method allow the skipping of iterations by modifying the index pa

Time:07-22

I'm trying to create a function that duplicates every 5 found in the provided array by using Array.prototype.forEach() and Array.prototype.splice():

function duplicateFives(array) {
  function multiplyFives (element, index) {
    if (element === 5) {
      array.splice(index, 0, 5);
      index  ;
    }
  }
  
  array.forEach(multiplyFives);

  return array;
}

However, it seems modifying the second parameter of the .forEach method doesn't skip iterations (elements). Is this correct, or am I making a different mistake?

Mdn does not seem to confirm nor specify any functionality related to the index parameter.

CodePudding user response:

If you want to split an array in chunks of n elements, Array.reduce may be a better idea.

const arr = [1,8,4,5,7,8,5,9,12,5,98,97,32,];
let chunks = arr.reduce( (a, v, i) => 
    i && i%5 === 0
     ? [...a, arr.slice(i-5, i)] : a, []);
// remaining elements
const remain = arr.slice(chunks.flat().length);

if (remain.length) {
  chunks = chunks.concat([remain]);
}

console.log(`${JSON.stringify(chunks)}`);

CodePudding user response:

You can not modify an array while iterating it with a forEach loop, which only provides local variables, like current element and index. Those are just local variables, modifying them does not affect the loop inside forEach.

What you should do is find indexes to be modified, and modify the array itself.

something like:

function duplicateFives(array) {
    array.map((cur,index)=>cur === 5 ? index : undefined) // find indexes of 5's
        .filter(item=>item !== undefined) // filter undefined's
        .forEach((item,index) => array.splice(item   index, 0, 5)); // modify array for those items. 
               // Adding new items to array changes indexes, take that into account.
    return array;
}

console.log(duplicateFives([1, 2, 3, 4, 5, 6, 7, 5, 8, 9, 10]));

CodePudding user response:

The index is limited to the scope of the multiplyFives() function and won't modify the index of the array.forEach() loop.

With your code, when a new element is spliced onto the array at the next index, the array.forEach() loop will see that element in the next iteration and continue splicing the same element for the remaining length of the array.

A boolean duplicate flag is required to allow duplicating adjacent 5 values and to ignore values that were already duplicated.

Here's the correct JavaScript code with comments explaining each modified line.

const array = [1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10]
console.log('Array without duplicated 5 values')
console.log(array)

function duplicateFives(array) {
    // Set a boolean flag to determine if a duplicate 5 should be made
    let duplicate = true

    function multiplyFives (element, index) {
        if (element === 5) {
            if (duplicate === true) {
                // Add a duplicate 5 to the array if the current element isn't from a previous duplication
                array.splice(index, 0, 5)
                // Prevent the duplicated 5 from duplicating itself in the next iteration
                duplicate = false
            } else {
                // Allow duplication for the next element with a value of 5 in the array
                duplicate = true
            }
        }
    }

    array.forEach(multiplyFives)
    return array
}

duplicateFives(array)
console.log('Array with duplicated 5 values')
console.log(array)

  • Related