I want to be able to multiply each array element by 3 different weighting factors.
User input = [24,3,0, 56,43,34]
Output = 24x7,3x3,0x1 + 56x7, 43x3, 34x0.. and repeat so basically at every 3 elements of the array a multiplication by 7, then 3, then 0 occurs.
It would look something like this:
For every array element multiply each array weighting factor and repeat when it gets to 3rd element
function multiplyWeightFact(input){
const weighting = [7,3,1]
for (let i = 0; i < input.length ; i++) {
console.log( input[0] * weighting[0])
console.log( input[1] * weighting[1])
console.log( input[3] * weighting[2])
break
}
for (let index = 0; index < input.length; index++) {
console.log( input[4] * weighting[0])
console.log( input[5] * weighting[1])
console.log( input[6] * weighting[2])
break
}
}
input from user = [24,3,0, 56,43,34]
and it continues if we have an array with lets say 100 numbers..
The output needs to be something like:
resultOutput = 374 when input is [24,10]
Of course the above function is not sustainable so any better way to do this?
You could map by taking an index and the remainder operator with the length of weighting.
const
multiplyBy = weighting => (v, i) => v * weighting[i % weighting.length],
array = [24, 3, 0, 56, 43, 34],
weighting = [7, 3, 1],
result = array.map(multiplyBy(weighting));
console.log(...result);
With x
const
multiplyBy = weighting => (v, i) => `${v}x${weighting[i % weighting.length]}`,
array = [24, 3, 0, 56, 43, 34],
weighting = [7, 3, 1],
result = array.map(multiplyBy(weighting));
console.log(...result);
You could just map over the input and multiply it by the weight based on it's index. We can then use remainder operator to keep the index within the range of the weight array.
function multiplyWeightFact(input, weight){
return input.map((num, index) => num * weight[index % weight.length]);
}
const weight = [7, 3, 0];
const input = [24, 3, 0, 56, 43, 34];
const result = multiplyWeightFact(input, weight);
console.log(result);
You can loop through the array elements and use the modulo operator to multiply with according to the position the right factor.
Modulo Explanation
Calculates the remainder.
const weighting = [7, 3, 1] // Instead of 3 weighting.length
1. 0 % 3 = 0 = Array Element = 7
2. 1 % 3 = 1 = Array Element = 3
3. 2 % 3 = 2 = Array Element = 1
4. 3 % 3 = 0 = Array Element = 7
And again ...
function multiplyWeightFact(input) {
const weighting = [7, 3, 1]
for (let index = 0; index < input.length; index++) {
input[index] *= weighting[index % weighting.length];
}
return input;
}
let input = [5,4,3,2,1]
console.log(multiplyWeightFact(input));
Related
Please bear with me this is difficult to explain. I will first explain how to do it successfully with only one set of data.
First, say I have an array like so yValuesMinusMean = [-5, -4, -1, 10]
I have another array like so xValuesMinusMean = [ 2.75,3.75,6.75,5.75 ]
Both of the above arrays can have numerous values. However, the length of both arrays is the same. So if the first one has 4, then the second one will definitely have 4.
I want to calculate the sum and product of the arrays. This is what I mean:
var sumOfXTimesYValues = this.calculateProductAndSum(yValuesMinusMean, xValuesMinusMean);
calculateProductAndSum(yValuesMinusMean = [], xValuesMinusMean = []) {
let total = 0;
for(let i = 0; i < yValuesMinusMean.length; i++) {
let product = (yValuesMinusMean[i] * xValuesMinusMean[i]);
total += product;
};
return total;
},
The result of this: console.log('sumOfXTimesYValues', sumOfXTimesYValues); is
17
LOGIC : (-5 * 2.75) + (-4 * 3.75) + (-1 * 6.75) + (10 * 5.25) = 17
So far, everything works. However, I want to make it so that instead of xValuesMinusMean being a single array with multiple numerical values, it will be a single array containing multiple arrays, with each array having the same number of elements as in yValuesMinusMean. Like so:
xValuesMinusMean = [ [ 2.75,3.75,6.75,5.75 ], [-2,-1,2,1]. .... ]
END GOAL: sumOfXTimesYValues = [17, 22, ...]
Logic for the second array item: (-5 * -2) + (-4 * -1) + (-1 * 2) + (10 * 1) = 22
Essentially, you're multiplying each value in each array in xValuesMinusMean with a value in yValuesMinusMean in the same order. So, -5 is the 0th item in the yValuesMinusMean array, and -2 is the 0th item in the array within xValuesMinusMean. So -5 * -2.
My next steps would be to do something like this:
xValuesMinusMean.forEach(element => {
for(let i = 0; i < xValuesMinusMean.length; i++) {
let product = (newCategoryArray[i] * xValuesMinusMean[i]);
total += product;
};
});
However, it yields the following: sumOfXTimesYValues = 352, which isn't correct. How would I be able to achieve the end goal?
END GOAL: sumOfXTimesYValues = [17, 22, ...]
Create a generic function for computing a scalar product (you've already got it):
function scalarProduct(a, b) {
let res = 0;
for(let i = 0; i < a.length; i++) {
res += a[i] * b[i];
}
return res;
}
and then map it over your matrix (array of vectors):
result = xValuesMinusMean.map(vec => scalarProduct(vec, yValuesMinusMean))
You can have one reduce function where you will take product of arrays and store it in accumulator.
const val =[ [ 2.75,3.75,6.75,5.25 ], [-2,-1,2,1]];
const yvalues = [-5, -4, -1, 10];
console.log(val.map(o=>o.reduce((a,e,i)=>a+=e*yvalues[i],0)));
Looks like your calculation is not correct first set of arrays will also return 22.
Live Demo :
const yValuesMinusMean = [-5, -4, -1, 10];
const xValuesMinusMean = [[2.75, 3.75, 6.75, 5.75], [-2, -1, 2, 1]];
const finalArr = [];
xValuesMinusMean.forEach(arr => {
let cal = 0;
arr.forEach((item, index) => {
cal += item * yValuesMinusMean[index]
});
finalArr.push(cal);
});
console.log(finalArr); // [22, 22]
I'm trying to create a function that groups an array of numbers based on a length parameter. The length represents the max length of each sub-array. The code works as it is meant to for getting the sub arrays, but what I'd like to do is make it sort by odd and even.
function myFunctionA(myArr1, myVal) {
newArr = [];
for ( x = 0; x < myArr1.length; x += myVal) {
newArr.push(myArr1.slice(x, x + myVal));
}
return newArr;
}
Console.log(myfunction([1,2,3,4,5,6,7,8,9,10],3))
This returns [[1,2,3],[4,5,6],[7,8,9],[10]]
What I'd like to do is go through each sub array at a time until the sub arrays are the correct length and add any leftover values to a sub array/s
This would look like
[[1,3,5][2,4,6][7,9][8,10]]
Since arr 0 and arr 1 are the correct length that we have stated in the console.log statement, 7 8 9 and 10 are left over. But since the can't create a full sub array and they are odds and even, they form two sub arrays with a side of 2.
Other examples:
myfunction([1,2,3,4,5,6,7],2)
Should return [[1,3],[2,4],[5,7],[6]]
myfunction([1,2,3,4,5,6,7,8],1)
Should return [[1][2][3][4][5][6][7][8]]
You could take an array for collecting all odd and even values and then push the group if it has zero items. By having the wanted size, create a new array.
function chunkenator(array, size, fn) {
let groups = [],
result = [];
for (let value of array) {
const group = fn(value);
if (!groups[group]) groups[group] = [];
if (!groups[group].length) result.push(groups[group]);
groups[group].push(value);
if (groups[group].length === size) groups[group] = [];
}
return result;
}
console.log(chunkenator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3, x => x % 2));
console.log(chunkenator([1, 3, 5, 7, 8, 9, 11, 13, 15], 3, x => x % 2));
One possibility would be to first seperate the numbers into even and odd numbers and then just loop over it, pushing the numbers into a new array switching between even and odd numbers.
It's not the cleanest piece of code, but it works.
function myfunction(arr, n) {
const evenOdd = arr.reduce((acc, e) => {
const ind = +(e % 2 === 0);
acc[ind] = acc[ind] || [];
acc[ind].push(e);
return acc;
}, []);
let ind = 0, res = [[]];
while (evenOdd[0].length || evenOdd[1].length) {
for (let i = n; i--;) {
const val = evenOdd[ind].shift();
if (val) res[res.length - 1].push(val)
}
ind = (ind + 1) % 2
res.push([])
}
res.pop()
return res;
}
for (const n of [1, 2, 3]) {
console.log(n,
myfunction([1, 2, 3, 4, 5, 6, 7, 8], n)
)
}
I want to find all possible maximum contiguous subarray averages from an array of values. Each array value represents the value at a duration, the number of seconds passed.
Ex. Input = [6, 4, 3, 10, 5]
Ex. Output = [5.6, 5.75, 6, 7.5, 10]
Output[0] = 6+4+3+10+5 / 5 = 5.6
Output[1] = 6+4+3+10 / 4 = 5.75
Output[2] = 3+10+5 / 3 = 6
Output[3] = 10+5 / 2 = 7.5
Output[4] = 10 / 1 = 10
The issue is that the real data has length of up to 40,000 values.
The result should have the same length as the input. I‘ve done a reduce on a subarray of specific lengths (only getting 5s, 60s, 3600s, etc. length), but that’s not a viable solution for each possible duration. Is there a way I can partition or otherwise create a specialized data structure to get these values? If not, how can I exclude durations as I go?
You can just take the reverse of the input array, then calculate sum and average incrementally. Then again taking the of output array.
const input = [6, 4, 3, 10, 5].reverse();
let output = [];
let total_sum = 0;
for (var i = 0; i < input.length; i++) {
total_sum += input[i];
let avg = total_sum / (i + 1);
output.push(avg);
}
console.log(output.reverse());
(You can even eliminate the reverse by looping the for loop in reverse order.)
Why not .map()? Mixed with reduce you could do something like this:
const output = [
[1, 2, 3, 4],
[5, 6, 7, 8]
];
const averages = output.map(
subarray =>
subarray.reduce(
(previousValue, currentValue) => previousValue + currentValue,
0
) / subarray.length
);
Where subarray is the collection of values, they're then added together and divided by the length of the subarray.
I hope this is what you mean
I have an array of this:
[34, 12, 56]
[100,125,19]
[30,50,69]
125 has been the highest value, it will return the index [1,1] format. Meaning 125 which is the highest value will return row 1 column 1
I was able to get the index in an array using this code
var a = [0, 21, 22, 7, 12];
var indexOfMaxValue = a.reduce((iMax, x, i, arr) => x > arr[iMax] ? i :
iMax, 0);
document.write("indexOfMaxValue = " + indexOfMaxValue); // prints
"indexOfMaxValue = 2"
Here's my approach. It flattens out all the arrays into more managable one, finds the max number and its index, and then calculates it's position using some math. Using a single array makes this calculation much easier.
const arr = [[34, 12, 56], [100,125,19], [30,50,69]];
const arr2 = [0, 21, 22, 7, 12];
function findHighest(arr) {
// Get the number of columns
const cols = arr.length;
// Flatten out the arrays
const tempArr = arr.flatMap(el => el);
// Get the max number from the array
const max = Math.max.apply(null, tempArr);
// Find its index
const indexMax = tempArr.findIndex(el => el === max);
// Find the remainder (modulo) when you divide the index
// by the number of columns
const mod = indexMax % cols;
// Return the final array output
return [Math.floor(indexMax / cols), mod];
}
console.log(findHighest(arr))
console.log(findHighest(arr2))
This will give the expected output but not sure is it good way to solve this:
var arr = [
[34, 12, 56],
[100, 125, 19],
[30, 50, 69]
];
var maxValue, maxIndex;
arr.forEach((arr1, i) => {
arr1.forEach((value, j) => {
if (i == 0 && j == 0) {
maxValue = value;
maxIndex = [i, j]
} else {
if (maxValue < value) {
maxValue = value;
maxIndex = [i, j];
}
}
});
});
console.log("Max Number Index", maxIndex);
If you mean 2d solution, try this. Should work for dynamic length arrays
This should be extendable with a new forEach for a new dimension
[100,125,19],
[30,50,69]];
maxIndex = [-1, -1];
maxElem = 0;
input.forEach(function(arr, row) {
console.error(row);
arr.forEach(function(e, col) {
if( maxElem <= e ) {
maxElem = e;
maxIndex = [row, col];
}
})
})
console.log(maxIndex)
I’m trying to generate all valid combinations of numbers from an array of digits. Let’s assume we have the following:
let arr = [1, 2, 9, 4, 7];
We need to output something like this:
1 2 9 4 7
1 2 9 47
1 2 94 7
1 2 947
1 29 4 7
1 29 47
1 294 7
1 2947
12 9 4 7
12 9 47
12 94 7
12 947
129 4 7
129 47
1294 7
12947
An invalid number would be 91, 497, 72 and so on.
I tried this but I’m not satisfied with the result:
const combination = (arr) => {
let i, j, temp;
let result = [];
let arrLen = arr.length;
let power = Math.pow;
let combinations = power(2, arrLen);
for (i = 0; i < combinations; i += 1) {
temp = '';
for (j = 0; j < arrLen; j++) {
if ((i & power(2, j))) {
temp += arr[j];
}
}
result.push(temp);
}
return result;
}
const result = combination([1, 2, 9, 4, 7]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Any ideas?
This code does what you want:
const arr = [1, 2, 9, 4, 7],
result = Array.from({length: 2 ** (arr.length - 1)}, (_, index) => index.toString(2).padStart(arr.length - 1, "0"))
.map((binary) => JSON.parse("[" + arr.map((num, position) => num + (Number(binary[position]) ? "," : "")).join("") + "]"));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
It results in:
[
[12947],
[1294, 7],
[129, 47],
[129, 4, 7],
[12, 947],
[12, 94, 7],
[12, 9, 47],
[12, 9, 4, 7],
[1, 2947],
[1, 294, 7],
[1, 29, 47],
[1, 29, 4, 7],
[1, 2, 947],
[1, 2, 94, 7],
[1, 2, 9, 47],
[1, 2, 9, 4, 7]
]
Assuming, the expected result does not depend on order, the spaces represent a binary pattern:
12947 => 0000
1294 7 => 0001
129 47 => 0010
…
1 29 47 => 1010
…
1 2 9 4 7 => 1111
We can utilize this pattern with a counter that we convert to a binary string. We also pad that string with 0 so it always remains 4 digits long:
index.toString(2).padStart(arr.length - 1, "0")
For n digits in arr, there are exactly 2n - 1 combinations, so we use:
{length: 2 ** (arr.length - 1)}
This is an object that has a length property of 2arr.length - 1.
We combine both those things into an Array.from call which accepts two arguments:
an object to turn into an array
a function for mapping each slot
Turning an object with a length property into an array means that we create an array with length many slots.
The mapping function accepts the index of a slot as the second parameter. We only use the index — as a counter for our binary number.
So, finally this whole expression:
Array.from({length: 2 ** (arr.length - 1)}, (_, index) => index.toString(2).padStart(arr.length - 1, "0"))
evaluates to the following array:
[
"0000",
"0001",
"0010",
"0011",
"0100",
"0101",
"0110",
"0111",
"1000",
"1001",
"1010",
"1011",
"1100",
"1101",
"1110",
"1111"
]
We need to further map this to the final result:
.map((binary) => …)
For each array element, binary is one of the binary strings from the array above.
In order to turn e.g. "0110" into something like "12,9,47", we need to map over arr as well. Every digit num from arr should be followed by , at position, iff binary is 1 at position:
arr.map((num, position) => num + (Number(binary[position]) ? "," : "")).join("")
The expression (Number(binary[position]) ? "," : "") evaluates binary at the specified position as a number. If it’s truthy, i.e. anything but 0, it evaluates to ",", if it’s falsy, i.e. 0, it evaluates to "".
So an intermediate array would look like ["1", "2,", "9,", "4", "7"]. All of this is joined together to "12,9,47".
Then, with JSON.parse("[" + … + "]") it’s being treated and parsed as an array, so it turns into [12, 9, 47]. Since these steps are applied for each binary string, you’ll end up with the final result.
2 ** (arr.length - 1) can be replaced by Math.pow(2, arr.length - 1) if ECMAScript 7 is not supported.
{length: 2 ** (arr.length - 1)} can be replaced by new Array(2 ** (arr.length - 1)).
(Number(binary[position]) ? "," : "") can be replaced by ["", ","][Number(binary[position])]. In this case the evaluated number will be used as an index for a temporary array.
So you need to iterate over all the combinations of "space" and "not space" between all the numbers. With n items, there will be n - 1 spaces, and 2 ** (n - 1) different lists.
So you could do something like this to get all the possible lists:
const combination = arr => {
const len = arr.length;
const n = Math.pow(2, len - 1);
const combinations = [];
for (let i = 0; i < n; i++) {
let this_combination = [arr[0]];
for (let j = 1; j < len; j++) {
if (i & Math.pow(2, j - 1)) {
// If the jth bit is on, no space. Append to the last element.
const last_index = this_combination.length - 1;
this_combination[last_index] = +(this_combination[last_index] + '' + arr[j]);
} else {
// Otherwise create a new list item.
this_combination.push(arr[j]);
}
}
// Consider making this function a generator and making this a yield.
combinations.push(this_combination);
}
return combinations;
}
const result = combination([1, 2, 9, 4, 7]);
console.log(result.map(line => line.join(' ')).join('\n'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
If you wanted each individual item seperately, for each item in the array, combine it with no other item, then just the next item, then the next 2 items, etc. untill the end:
const combination = arr => {
const len = arr.length;
const combinations = [];
for (let i = 0; i < len; i++) {
let item = arr[i];
combinations.push(item);
for (let j = i + 1; j < len; j++) {
item = +(item + '' + arr[j]);
combinations.push(item);
}
}
return combinations;
}
const result = combination([1, 2, 9, 4, 7]);
console.log(result.join('\n'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could take a recursive approach by iterating the array and insert a space or not and fork the calling of the same function with an incremented index.
function combine(array) {
function fork(i, p) {
if (i === array.length) {
result.push(p);
return;
}
fork(i + 1, p + ' ' + array[i]);
fork(i + 1, p + array[i]);
}
var result = [];
fork(1, array[0].toString());
return result;
}
console.log(combine([1, 2, 9, 4, 7]));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could do this by using below code where 3 pointer is used,
1st pointer print 0th position to cursor position.
2nd pointer print cursor to diffidence position in each iteration .
3rd pointer print cursor position to last position.
let arr = [1, 2, 9, 4, 7];
console.log(arr.join(','));
for(let diff=2;diff<=arr.length;diff++){
for(i=0,j=diff;arr.length>=i+diff;j++,i++){
var temp = [];
if(i>0)
temp.push(arr.slice(0,i).join(','));
temp.push(arr.slice(i,j).join(''));
if(j<arr.length)
temp.push(arr.slice(j,arr.length).join(','));
console.log(temp.join(','));
}
}