Javascript forEach loop won't continue to next iteration

Viewed 878

I am trying to do this challenge where the function should return the index value of the element when the sum of the values on either side of the element are equal. E.g. [1,2,3,4,3,2,1] should return 3, since on the other sides of '4' the values add to 6 (1+2+3) and (3+2+1). Also if there is no such value then the function should return -1.

function findEvenIndex(arr) {
  arr.forEach((element, index) => {
    let a = arr.splice(index + 1, arr.length); //array of values after current value
    let b = arr.splice(arr[0], index); //array of values before current value
    let suma = a.reduce((accumulator, currentValue) => { //Sum of array of after values
      return accumulator + currentValue;
    }, 0);
    let sumb = b.reduce((accumulator, currentValue) => { //Sum of array of before values
      return accumulator + currentValue;
    }, 0);
    if (suma === sumb) {  //comparing the two sums to check if they are equal
      return index;
    };
  });
};

My understanding was that if suma and sumb are NOT equal, then the next iteration of the forLoop will begin, however this does not happen and I cannot see why.

The function should return -1 if no such value exists, I haven't implemented this part of the code currently.

Thanks

4 Answers

There are two issues to your code:

  1. As I have pointed out in my comment, Array.prototype.slice mutates/changes the array in place, which is a bad idea when you are also iterating through the array at the same time. Therefore, make a shallow copy of the array before splicing it, by using the spread operator, i.e. [...arr].splice()
  2. You are returning from a foreach function, but not returning from the outer findEvenIndex() function.

A better solution is to simply use a for loop: once an index is found, we can use break to short-circuit and break out of the loop since we do not want to perform further analysis. We store the index in a variable outside of the for loop, and return it:

function findEvenIndex(arr) {
  let foundIndex = -1;
  
  for(let index = 0; index < arr.length; index++) {
    const a = [...arr].splice(index + 1, arr.length); //array of values after current value
    const b = [...arr].splice(0, index); //array of values before current value
    
    const suma = a.reduce((accumulator, currentValue) => { //Sum of array of after values
      return accumulator + currentValue;
    }, 0);
    const sumb = b.reduce((accumulator, currentValue) => { //Sum of array of before values
      return accumulator + currentValue;
    }, 0);
    
    if (suma === sumb) {  //comparing the two sums to check if they are equal
      foundIndex = index;
      break;
    };
  };
  
  return foundIndex;
};

console.log(findEvenIndex([1,2,3,4,3,2,1]));

you should use slice method instead of splice and return index out of loop


function findEvenIndex(arr) {
  
  var result =  -1;
  arr.forEach((element, index) => {
    let a = arr.slice(index + 1);  
    let b = arr.slice(0, index);  
    let suma = a.reduce((accumulator, currentValue) => {
      //Sum of array of after values
      return accumulator + currentValue;
    }, 0);
    let sumb = b.reduce((accumulator, currentValue) => {
      //Sum of array of before values
      return accumulator + currentValue;
    }, 0);
    if (suma === sumb) {
      //comparing the two sums to check if they are equal
        result =   index;
    }
  });
  return result;
}

also you can do it using findIndex method

const sum  = (a,b)=> a+b;
const findEvenIndex = (TestArr) =>
  TestArr.findIndex(
    (_, i) =>
      TestArr.slice(0, i).reduce(sum, 0) === TestArr.slice(i + 1).reduce(sum, 0)
  ); ;

A few notes. Take advantage of the built in .findIndex(). Use slice, as it returns an altered copy of the array. slice/splice take indices as arguments, so do not use arr[0] in these methods.

function findEvenIndex(arr) {
  return arr.findIndex((element, index) => {
    let a = arr.slice(index + 1); //array of values after current value
    let b = arr.slice(0, index); //array of values before current value
    let suma = a.reduce((accumulator, currentValue) => { //Sum of array of after values
      return accumulator + currentValue;
    }, 0);
    let sumb = b.reduce((accumulator, currentValue) => { //Sum of array of before values
      return accumulator + currentValue;
    }, 0);
    return suma===sumb;
  });
};

You could take a fast approach without changing the array and use two indices and a variable for the actual delta which is build by adding left side values and subtracting right side values.

If the indices are not in order exit the loop.

Then check delta. If delta is zero return left index or -1 for not found separating index.

function getIndex(array) {
    let delta = 0,
        i = 0,
        j = array.length - 1;

    while (i < j) {    
        if (delta <= 0) {
            delta += array[i++];
            continue;
        }
        delta -= array[j--];
    }
    
    return delta ? -1 : i;
}

console.log(getIndex([1, 2])); // -1
console.log(getIndex([1, 2, 3, 4, 3, 2, 1])); // 3
console.log(getIndex([1, 2, 2, 2, 4, 3, 2, 2])); // 4

Related