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
There are two issues to your code:
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()
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
My task is to sum elements of an array and add it to second parameter (number) using recursion.
Return only gives me last value of sum. I would appreciate any feedback :)
const getArraySum = (numbersArray, initialValue) => {
// let sum = initialValue
// for (let i = 0; i < numbersArray.length; i++) {
// sum += numbersArray[i]
// } return sum
if (numbersArray.length === 0 ) {
return initialValue
} else {
let sum = 0
sum += numbersArray[numbersArray.length-1]
console.log (numbersArray)
numbersArray.pop()
console.log (sum)
getArraySum (numbersArray)
return sum + initialValue
}
};
const result1 = getArraySum([4,7,10], 5)
console.log (result1)
You're ignoring the return value of the recursive call to getArraySum. Instead, you should add it to the returned value:
const getArraySum = (numbersArray, initialValue) => {
if (numbersArray.length === 0) {
return initialValue
}
return numbersArray.pop() + getArraySum(numbersArray, initialValue);
};
const result = getArraySum([4,7,10], 5)
console.log (result)
Note that the initialValue should only be taken into consideration once, in the end condition where the array is empty.
The idea is to split an array into head (=the first element or null for an empty array) and tail (everything else). Then, establish that the sum is head + sum(tail):
let sum = ([head = null, ...tail]) =>
head === null ? 0 : head + sum(tail)
console.log(sum([1,2,3,4]))
Having an initial value is a silly requirement, but it goes the same way:
let sum = ([head = null, ...tail], init = 0) =>
init + (head === null ? 0 : head + sum(tail))
console.log(sum([1, 2, 3, 4], 100))
You could take the single values a summing variable and return immediately if the array is empty.
Otherwise return the function call with a new shorter array and hte sum of sum and the first element.
const
getSum = (numbers, sum = 0) => {
if (!numbers.length) return sum;
return getSum(numbers.slice(1), sum + numbers[0]);
};
console.log (getSum([4, 7, 10], 5));
As long as the array has an element, return last element (pop) plus getArraySum([rest of the array]), otherwise return initial value:
const getArraySum = (numbersArray, initialValue) => {
if (numbersArray.length === 0 ) {
return initialValue
} else {
return numbersArray.pop() + getArraySum(numbersArray, initialValue);
}
};
const result1 = getArraySum([4,7,10], 5)
console.log (result1)
Hi I am doing addition of key value from objects of an array. I want to exclude the object from the addition if it has some conditions. Example:
var arrItem = [{"id": 1, "value":100},{"id": 2, "value":300},{"id": 3, "value":400}];
//addition
this.sum = arrItem.map((a:any) => a.value).reduce(function (a:any, b:any) {
return a + b;
});
console.log(this.sum) // ====>>> getting 800
I want to exclude object with id==2 from summation. How I can filter this out so that I will get result as ==> 500
You can do it with reduce:
this.sum = arrItem.reduce((acc, val) => {
if (val.id !== 2) return acc + val.value;
return acc;
}, 0);
I have an array as below. How can previous value be copied to the array when zero occurs.
var array_numbers = [9,0,1,0,2,0,3];
var Result_array = [9,9,1,1,2,2,3];
i am able to get filter out all zeros with below code, but need to copy the previous values in the array
arr.filter(Boolean)
This is a great use of the .map() function, because every input needs an output, even if it changes.
var result_array = array_numbers.map(function(val, index, array) {
// the OR operator will move on if val is falsy... like zero
return val || array[index - 1];
});
I simplified the check, but it doesn't handle some scenarios, like if the first value is zero, or other falsy values.
Since multiple consecutive zeros are possible, one option is to hold the last non-zero value in state:
const numbers = [9, 0, 1, 0, 2, 0, 0, 3];
let last;
const result = numbers.map(n => last = n || last);
console.log(result);
Another option is to implement a “scan” that works like reduce but keeps every value produced:
const scanl1 = (array, f) => {
if (array.length === 0) {
return [];
}
let x = array[0];
const result = [x];
for (let i = 1; i < array.length; i++) {
x = f(x, array[i]);
result.push(x);
}
return result;
};
const numbers = [9, 0, 1, 0, 2, 0, 0, 3];
const result = scanl1(numbers, (m, n) => n || m);
console.log(result);
You can use .map instead of .filter, if the current index is greater than 0 you return the previous index, otherwise the current value. Not sure what you want to do with [0, 0, 0]...
const input = [9,0,1,0,2,0,3]
const output = input.map((item, index, arr) => {
if (item === 0 && index > 0) {
return arr[index-1]
}
return item
})
console.log(output)
You don't want to filter it, since you're trying to end up with an array of the same length.
What you should do, is iterate the array, and grab the item at the previous index when a 0 is found. You can use || to get the last array item for the first member if needed.
var array_numbers = [9,0,1,0,2,0,3];
var result = array_numbers.map(function(n, i, arr) {
return n === 0 ? arr[(i || arr.length)-1] : n;
});
console.log(result);
If both the first and last are 0, the first won't get changed.
I can sum each value in the array but I can't figure out how to get the sum of each number multiplied by its position in the array.
Create a variable that stores product of the index and array element. Then add that to array element and store it to sum.
var myProd=1;
var mySum=0;
for(var i = 0 ; i<myArray.length() ; i++)
{
myProd = (i+1)*myArray[i];
mySum+=(myArray[i]+myProd);
}
You can use the reduce method for arrays: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
var myArray = [1,2,3,4];
var result = myArray.reduce(function(prev, curr, index) {
return prev + (curr * index);
}, 0);
console.log(result);
Which is effectively the same as (1*0 + 2*1 + 3*2 + 4*3)
Define a function to sum up the values in an array:
function sum(array) { return array.reduce(function(a, b) { return a + b; }); }
Now create an array of each value multiplied by its position, then apply sum to it:
sum(myArray.map(function(elt, idx) { return elt * idx; }))
In ES6, you can write this more compactly:
function sum(array) { return array.reduce((a, b) => a + b); }
sum(myArray.map((elt, idx) => elt * idx));
I want to find the indexes of the minimum of an array.
E.g.
var array = [1,2,3,4,1,7,8,9,1];
var min = Math.min.apply( Math, array )
var key = array.indexOf(min);
The problem is that Math.min.apply return only the first index
min = 1 and key = 0
What I want to do is to return
min = 1 and key = [0,4,8];
Is it possible to do it with Math.min.apply?
var array = [1,2,3,4,1,7,8,9,1];
var min = Math.min.apply( Math, array )
var arrayWithIndex = array.map(function(element, index) {
return element + "-" + index;
});
var minValues = arrayWithIndex.filter(function(element) {
return Number(element.split('-')[0]) === min;
});
var keys = minValues.map(function(element) {
return Number(element.split('-')[1]);
});
My algorithm is mapping the original array to include a new array that contains both the number and index. I'm then filtering that array for elements, where the number is equal to min, and then mapping again to find the index.
You can also chain these methods
return array.map(function(element, index) {
return element + "-" + index;
})
.filter(function(element) {
return Number(element.split('-')[0]) === min;
}).
.filter(function(element) {
return Number(element.split('-')[1]);
});
An Array.prototype.reduce should do the work.
var array = [1, 2, 3, 4, 1, 7, 8, 9, 1];
function getMinKeys(array) {
var min = Math.min.apply(Math, array);
return array.reduce(function (r, a, i) {
a === min && r.push(i);
return r;
}, []);
}
document.write('<pre>' + JSON.stringify(getMinKeys(array), 0, 4) + '</pre>');
var array = [1,2,3,4,1,7,8,9,1];
function findMinimumIndexes(array) {
var min = Math.min.apply(Math, array);
var indexes = [];
array.forEach(function(item, idx, arr) {
if (item === min) {
indexes.push(idx);
}
});
return indexes;
}
console.log(findMinimumIndexes(array));
The function declares the variable indexes and assigns to it an empty array which then it fills up using a forEach call with elements' indexes whose value matches min.
Notice that this only works for primitive values since it uses === to check for equivalence.
To make it work on arrays or objects that are 'deeply equal' to the one you are looking for, you would need a more rigorous implementation.