Find indexes of multiple minimum in an array in javascript - javascript

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.

Related

Javascript forEach loop won't continue to next iteration

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

How to populate an array with integers

Please, how do you populate an array say ‘num’ with numbers not in a second array say ‘fig’? I’m trying to use a loop to have the values of the already populated array ‘fig’ compared to ‘num’ which is to be populated with integers not found in ‘fig’. I’m a bit confused.
If you need to do an array with n numbers you can use this two ways.
const arrayLength = 100;
const numberArray = [...new Array(arrayLength).keys()]
const anotherWay = new Array(arrayLength).fill().map((_, idx) => idx + 1);
console.log(numberArray, anotherWay)
so to do this we have to do a few things:
1) define an existing array with numbers to avoid
2) define length on new array
3) generate a random number and make it an integer
4) check to see if we need to avoid
5) if it's a new value add it to the second array
var first=[55,45,35,1,2,3,4,5];
var second = [];
var i = 7;
var x;
while (i != 0){
x = ~~(Math.random()*100);
var check = false;
for(let j=0; j<first.length;j++){
if(x == first[j]){
check = true;
}
}
if(!check){
second.push(x);
i--;
}
}
console.log(second);
const fig = [-21, 0, 3, 6, 7, 42]
const min = Math.min(...fig) // or fig[0] if the the array is already sorted
const max = Math.max(...fig) // or fig[fig.length - 1]
const num = Array.from({ length: max - min }, (_, i) => i + min)
.filter(el => !fig.includes(el))
or, saving one loop
const num = Array.from({ length: max - min }).reduce((acc, _, i) => {
const curr = i + min
if (!fig.includes(curr)) {
return acc.concat(curr)
}
return acc
}, [])
This is assuming your range is from the smallest number in fig to the largest in fig.

How to sort and list out the array element, after comparing the sums of each numeric value

This code returns only returns the order of the sums of the numeric value, how do I return the array element in a list arranged by largest sum on top?
For instance, the result should be:
"1234-2722-2343-2842"
"1234-2722-2343-2345"
"1234-2322-2343-2342"
Code:
var addSum = function(ccNum) {
var sum = 0;
for (var i=0; i<ccNum.length; i++ ) {
var eachLetter = ccNum.charAt(i);
if (!isNaN(eachLetter)) {
sum += +eachLetter;
}
}
return sum;
};
var ccNums = ["1234-2322-2343-2342","1234-2722-2343-2345", "1234-2722-2343-2842"];
var checkNums = [];
for (var i=0; i<ccNums.length; i++) {
var ccNum = ccNums[i];
var sum = addSum(ccNum);
console.log("The checksum of CC number:"+ccNum+" is "+sum);
checkNums.push(sum);
}
checkNums.sort(function(a,b) {
return b-a;
});
console.log(checkNums);
The solution using String.replace, String.split, Array.map, Array.filter and Array.reduce:
var ccNums = ["1234-2322-2343-2342","1234-2722-2343-2345", "1234-2722-2343-2842"],
getSum = function(num){
return num.replace("-", "").split("").map(Number).filter(Boolean).reduce(function(prev, next){
return prev + next;
});
};
ccNums.sort(function (a, b) {
return getSum(b) - getSum(a);
});
console.log(ccNums);
The output:
["1234-2722-2343-2842", "1234-2722-2343-2345", "1234-2322-2343-2342"]
I suggest use Sorting with map, because it uses only one iteration for the sum of a string and uses it until the sorts end. Then it rebuilds a new array with the sorted items.
var ccNums = ["1234-2322-2343-2342", "1234-2722-2343-2345", "1234-2722-2343-2842"];
// temporary array holds objects with position and sort-value
var mapped = ccNums.map(function (el, i) {
return {
index: i,
value: el.split('').reduce(function (r, a) { return r + (+a || 0); }, 0)
};
});
// sorting the mapped array containing the reduced values
mapped.sort(function (a, b) {
return b.value - a.value;
});
// container for the resulting order
var result = mapped.map(function (el) {
return ccNums[el.index];
});
console.log(result);
Use Array#sort with help of String#split and Array#reduce methods
var ccNums = ["1234-2322-2343-2342", "1234-2722-2343-2345", "1234-2722-2343-2842"];
// function to get sum of numbers in string
function sum(str) {
// split string
return str.split('-')
// iterate and get sum
.reduce(function(a, b) {
// parse string to convert to number
return a + Number(b); // in case string contains no-digit char that for avoiding NaN use "return a + ( parseInt(b, 10) || 0 )
}, 0); //set initial value to avoid 2 parsing
}
// call sort function
ccNums.sort(function(a, b) {
// find out sum and compare based on that
return sum(b) - sum(a);
});
console.log(ccNums)
Or much better way would be, store the sum in an object and refer in sort function which helps avoid calling sum function multiple times.
var ccNums = ["1234-2322-2343-2342", "1234-2722-2343-2345", "1234-2722-2343-2842"];
// function to get sum of numbers in string
function sum(str) {
// split string
return str.split('-')
// iterate and get sum
.reduce(function(a, b) {
// parse string to convert to number
return a + Number(b);
}, 0); //set initial value to avoid 2 parsing
}
var sumArr = {};
// create object for referncing sum,
// which helps to avoid calling sum function
// multiple tyms with same string
ccNums.forEach(function(v) {
sumArr[v] = sum(v);
});
// call sort function
ccNums.sort(function(a, b) {
// find out sum and compare based on that
return sumArr[b] - sumArr[a];
});
console.log(ccNums)

Remove all items that have duplicates in array Javascript

I have searched on here and have not found a solution. Obviously I will be corrected if I am wrong. What I am trying to do is return values that do not have a duplicates in an array.
Examples:
myArr = [2,1,2,3] // answer [1,3]
myArr = [3,1,2,2,3] // answer [1]
I would post some code but I have not been able to figure this out myself and the only code examples I have found are for removing any duplicate values.
The possible solution above is to return no duplicates... I am trying to return values that are don't have duplicates.
One option is to use the optional second argument to indexOf to find duplicate indexes. Consider that for a given element e and an index i:
if e is the first of two identical elements in the array, indexOf(e) will return i and indexOf(e, i + 1) will return the index of the second element.
if e is the second of two identical elements in the array, indexOf(e) will return the index of the first element, and indexOf(e, i + 1) will return -1
if e is a unique element, indexOf(e) will return i and indexOf(e, i + 1) will return -1.
Therefore:
myArr.filter(function (e, i, a) {
return a.indexOf(e) === i && a.indexOf(e, i + 1) === -1
});
var isUnique = function(v,i,arr){
// return true if the first occurrence is the last occurrence
return ( arr.indexOf(v) === arr.lastIndexOf(v) );
};
var uniqueVals = myArr.filter(isUnique);
console.log( uniqueVals );
If is not an associative array (your case):
var myArr = [1,2,2,3,4,4,1,5];
var myNewArr = [];
if (myArr.length > 0 )
{
myNewArr[0] = myArr[myArr.length-1];
}
var count = 1;
myArr.sort();
for (var i = myArr.length - 2; i >= 0; i--) {
if(myArr[i] != myArr[i-1])
{
myNewArr[count] = myArr[i];
count++;
}
}
var yourArray = [1, 2, 1, 3];
var uniqueValues = [];
$.each(yourArray, function (i, value) { //taking each 'value' from yourArray[]
if ($.inArray(value, uniqueValues) === -1) {
uniqueValues.push(value); // Pushing the non - duplicate value into the uniqueValues[]
}
});
console.log(uniqueValues);
Result: [1,2,3];

How do I find the sum of each number multiplied by its position in the array in Javascript?

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));

Categories