Fill an array asynchronously - node.js

I have two arrays here, filling one of them with random numbers:
var arr1 = [1];
var arr2 = [];
function arr1Filler() {
arr2 = arr1;
setTimeout(function() {
for (var i = 0; i < 3; i++) {
arr1[i] = Math.floor(Math.random()*5);
}
console.log('array 1:');
console.log(arr1);
console.log('array 2:');
console.log(arr2);
}, 500);
}
setInterval(arr1Filler, 1000);
in this example, why these two arrays are always equal. In other words, why I am getting something like this:
array 1:
[ 3, 0, 1 ]
array 2:
[ 3, 0, 1 ]
array 1:
[ 0, 2, 3 ]
array 2:
[ 0, 2, 3 ]
array 1:
[ 1, 2, 4 ]
array 2:
[ 1, 2, 4 ]
instead of a result like this (the last value of array 2 is the new value of array 1):
array 1:
[ 1 ]
array 2:
[ 3, 0, 1 ]
array 1:
[ 3, 0, 1 ]
array 2:
[ 0, 2, 3 ]
array 1:
[ 0, 2, 3 ]
array 2:
[ 1, 2, 4 ]
What should I do to get the second result which I expect?

They are the same because you set the arrays to the same object here:
arr2 = arr1;
So when you add to arr1, arr2 is always identical. What you want is a copy of arr1. You can use slice to effectively make a copy of an array.
arr2 = arr1.slice();
var arr1 = [1];
var arr2 = [];
function arr1Filler() {
arr2 = arr1.slice();
setTimeout(function() {
for (var i = 0; i < 3; i++) {
arr1[i] = Math.floor(Math.random()*5);
}
console.log('array 1:');
console.log(arr1);
console.log('array 2:');
console.log(arr2);
}, 500);
}
setInterval(arr1Filler, 1000);

Related

reducing an array of nested objects in javascript

so i have this array and i want to return the sum of lci and the sum of mci with a reduce function
const data = [{ option:{ lci: 1, mci: 2 } }, { option:{ lci: 3, mci: 4 } }, { option:{ lci: 5, mci: 6 } }];
i have tried this but it's not working:
data.reduce( (previousValue, currentValue) => {
return {
totalLCI: previousValue.option.lci + currentValue.option.lci,
totalMCI: previousValue.option.lci + currentValue.option.lci,
};
})
reduce method takes 2 important args: your reducing function and the default value at step 0 of the iteration
Here the reducer has 2 args:
the so-called previousValue: here called reducerTarget as it receives what is returned in the body of the reducer
the currentValue where the reducer is: here called currentArrayItem
Here's what you might want
const {totalLCI, totalMCI} = data.reduce((reducerTarget, currentArrayItem) => {
return {
totalLCI: reducerTarget.totalLCI + currentArrayItem.option.lci,
totalMCI: reducerTarget.totalMCI + currentArrayItem.option.mci
}
}, {totalLCI: 0, totalMCI: 0})
From here, starting with the default value, what it does on the first iteration is
/* 1st step:
index = 0
targetReducer = defaultValue = {totalMCI: 0, totalLCI: 0}
currentArrayItem = {option: {lci: 1, mci: 2}}
*/
return {
totalLCI: 0 + 1,
totalMCI: 0 + 2
}
/* 2nd step:
index = 1
targetReducer = previousValue = {totalMCI: 1, totalLCI: 2}
currentArrayItem = {option: {lci: 3, mci: 4}}
*/
return {
totalLCI: 1 + 3,
totalMCI: 2 + 4
}
First you need know if you have stored value in the fields totalLCI and totalMCI, if they aren't set, add the previous value and the current value, after add, return the values, in the next iteration, you will check again if the data is stored in totalLCI and totalMCI, after that, you will get data stored in that field and sum it all the time till finish the iteration, here an example:
var data2 = [{ option:{ lci: 1, mci: 2 } }, { option:{ lci: 3, mci: 4 } }, { option:{ lci: 5, mci: 6 } }];
let test = data2.reduce( (previousValue, currentValue) => {
if(!previousValue.totalLCI && !previousValue.totalMCI){
return {
totalLCI: previousValue.option.lci + currentValue.option.lci,
totalMCI: previousValue.option.mci + currentValue.option.mci
};
}else{
return{
totalLCI: previousValue.totalLCI + currentValue.option.lci,
totalMCI: previousValue.totalMCI + currentValue.option.mci
}
}
});
console.log(test.totalLCI);
console.log(test.totalMCI);

Can't create worksheet in a loop

let workbook = new Excel.Workbook();
for (let i = 0; i < 3; i++){
workbook.addWorksheet('test', {
properties: {tabColor: {argb: 'FF00FF00'}}, views: [
{ySplit: 5, activeCell: 'A1', showGridLines: false}
]
});
}
First worksheet will have 'test' name, others will have an error title. Do you know how to make it work?
EDIT : If i generate my worksheet in a function, it works.
let workbook = new Excel.Workbook();
function generateWorksheet(data){
workbook.addWorksheet('test', {
properties: {tabColor: {argb: 'FF00FF00'}}, views: [
{ySplit: 5, activeCell: 'A1', showGridLines: false}
]
});
}
for (let i = 0; i < 3; i++){
generateWorksheet(i);
}
I think the issue is that you can't create multiple worksheets with the same name. So append the loop index to each worksheet.
let workbook = new Excel.Workbook();
for (let i = 0; i < 3; i++){
workbook.addWorksheet('test'+i, {
properties: {tabColor: {argb: 'FF00FF00'}}, views: [
{ySplit: 5, activeCell: 'A1', showGridLines: false}
]
});
}
So now the worksheet name would be test plus the loop index.

Compare two object key values, return minimum denominator

I am new to NodeJS coming from Python and having trouble with this practice problem.
Given two objects (key, value pairs) return the minimum denominator between them.
ObjectA = {"A": 10, "B": 20, "C": 30} "Stock"
ObjectB = {"A": 5, "B": 10, "C": 1} "Per Item"
function(objectA, objectB) would return 2 since ObjectB can go into ObjectA "fully" 2 times.
In my mind or Python, I would for loop each key/value compare the two objects. Not sure how to do this in a performance way/deal with it if key-values are out of order.
Unsure how to iterate through these objects in JavaScript, would I have to call each child independently? How do I index them?
main.js:
function howMany(params) {
const {objectA, objectB} = params
Object.keys(objectA).reduce((denominator, key) => {
if(objectB[key] === undefined) {
return 0;
}
const d = Math.floor(objectA[key] / objectB[key]);
return d < denominator ? d : denominator;
}, Infinity);
}
module.exports = {howMany}
var params = require('./inputs.js');
howMany(params.returnsOne);
console.log(howMany(params.returnsOne));
inputs.js:
module.exports = {
returnsOne: {
objectA: {
a: 10,
b: 5,
c: 5
},
objectB: {
a: 20,
b: 10,
c: 5
}
}
}
You could use the spread syntax to pass all the ratios to Math.min and then truncate the result:
var objectA = { A: 10, B: 20, C: 30 },
objectB = { A: 5, B: 10, C: 1 },
denominator = Math.floor(Math.min(...Object.keys(objectA).map(
key => objectA[key] / objectB[key] ))) || 0;
console.log(denominator);
More integrated with what you have as context:
function howMany({objectA, objectB}) {
return Math.floor(Math.min(...Object.keys(objectA).map(
key => objectA[key] / objectB[key] ))) || 0;
}
const params = {
returnsOne: {
objectA: { A: 10, B: 20, C: 30 },
objectB: { A: 5, B: 10, C: 1 }
}
};
console.log(howMany(params.returnsOne));
You could reduce the keys and take the one with the smalles value of the division.
var objectA = { A: 10, B: 20, C: 30 },
objectB = { A: 5, B: 10, C: 1 },
keys = Object.keys(objectA),
key = keys.reduce(function (a, b) {
var aa = Math.floor(objectA[a] / objectB[a]),
bb = Math.floor(objectA[b] / objectB[b]);
return aa < bb ? a : b;
}),
denominator = Math.floor(objectA[key] / objectB[key]);
console.log(denominator);
Iterate the Object#keys of ObjectA with Array#reduce, and on each iteration assign the denominator to the current lowest, or to 0 if key is missing in ObjectB:
const ObjectA = {"A": 10, "B": 20, "C": 30};
const ObjectB = {"A": 5, "B": 10, "C": 1};
const findBinA = (objectA, objectB) => Object.keys(objectA)
.reduce((denominator, key) => {
const d = Math.floor(objectA[key] / objectB[key]) || 0;
return d < denominator ? d : denominator;
}, Infinity);
console.log(findBinA(ObjectA, ObjectB));

TriangularSolver in Math.Net

Are any of the existing solvers equivalent to this TriangularSolver from the Java ejml library?
In particular I need a function that solves the lower triangular matrix using forward substitution.
I ended up implementing a lower triangular matrix solver myself:
public static Vector<double> SolveLower(this Matrix<double> a, Vector<double> b)
{
if (a.RowCount != a.ColumnCount)
{
throw new ArgumentException("Matrix must be square.");
}
if (a.RowCount != b.Count)
{
throw new ArgumentException("Matrix row and Vector must be the same length.");
}
var x = b.Clone();
double sum;
for (int row = 0; row < a.ColumnCount; row++)
{
sum = x.At(row);
for (int col = 0; col < row; col++)
{
sum -= a.At(row, col) * x.At(col);
}
x[row] = sum / a.At(row, row);
}
return x;
}
Test method:
[TestMethod]
public void TestSolveLowerMatrix()
{
var a = Matrix<double>.Build.DenseOfArray(new double[,] { { 3, 0, 0, 0},
{ -1, 1, 0, 0 },
{ 3, -2, -1, 0 },
{ 1, -2, 6, 2}});
var b = Vector<double>.Build.DenseOfArray(new double[] { 5, 6, 4, 2 });
var x = a.SolveLower(b);
// Verify results are valid
var expected = Vector<double>.Build.Dense(new double[] { 5 / 3.0, 23 / 3.0, -43 / 3.0, 305 / 6.0 });
Assert.AreEqual(expected.ToString(), x.ToString());
// Double check that A*x = b
Assert.AreEqual(b.ToString(), (a * x).ToString());
}

Couchdb rereduce understanding and sum

I don't know if this is really rereduce but that's why I'm here.
I have this:
"afrikan" ID: f6733302df85ac109397f4b6030005bf [1, 2]
"afrikan" ID: f6733302df85ac109397f4b6030006d1 [1, 3]
"afrikan" ID: f6733302df85ac109397f4b6030012b6 [2, 4]
"chinese" ID: f6733302df85ac109397f4b6030012eb 1
"chinese" ID: f6733302df85ac109397f4b603001d87 1
I know how to calculate the sum if the value wasn't an array (like in
chinese). But I can't manage to sum the values in the array and it
results in this: "afrikan" "02,41,31,2"
And one more question: is there a way to sum all the values regardless
of keys?
View code:
function(doc) {
if(doc.food) {
emit(doc.food, doc.type);
}
}
Reduce code:
function(keys,values,rereduce)
{
return sum(values);
}
Thank you a lot :)
UPDATE:
I found an answer for Couchdb.
Here is the code:
function(doc) {
if(doc.food) {
if(doc.type.length>1) {
doc.type.forEach(function(tag) {
emit(doc.food,tag);
});
}else {
emit(doc.food,doc.type);
}
}
}
Reduce:
function(keys,values) {
return sum(values);
}
The reason you get "02,41,31,2" is because Javascript will convert a number + an array into a string. It is very strange, but true.
> 0 + [2, 4] + [1, 3] + [1, 2]
'02,41,31,2'
> sum([0, [2, 4], [1, 3], [1, 2]]) // Same result
'02,41,31,2'
I think you do not need to worry about rereduce. Just add every value together. If it is an array, add all the values in the array.
function(keys, values, rereduce)
{
var total = 0;
var i, j;
for(i = 0; i < values.length; i++) {
if(typeof values[i] == "number") {
total = total + values[i];
}
else {
for(j = 0; j < values[i].length; j++) {
total = total + values[i][j];
}
}
}
}

Resources