Get cell of 2D Matrix in Google Spreadsheet - javascript

I have this function as a custom function in Google Apps Script being used in a spreadsheet:
function MultiplyMatrix(m2, m1) {
var result = [];
for(var j = 0; j < m2.length; j++) {
result[j] = [];
for(var k = 0; k < m1[0].length; k++) {
var sum = 0;
for(var i = 0; i < m1.length; i++) {
sum += m1[i][k] * m2[j][i];
}
result[j].push(sum);
}
}
return result;
}
Is there a way to get a specific index of the array without getting the whole result matrix input into the spreadsheet, If so what is the syntax?
I have this:
I want just this:

As I cannot comment, I'll use an answer. Given how your question is formulated, a simple answer can be to change your custom function definition so that it takes two extra parameters, the row index and column index of the result you're interested in; hence your code becomes:
function MultiplyMatrix(m2, m1, row, col) {
var result = [];
for(var j = 0; j < m2.length; j++) {
result[j] = [];
for(var k = 0; k < m1[0].length; k++) {
var sum = 0;
for(var i = 0; i < m1.length; i++) {
sum += m1[i][k] * m2[j][i];
}
result[j].push(sum);
}
}
return result[row][col];
}
You can then call your function as =MultiplyMatrix(A1:B2, C3:D4, 1, 1) to get the value of the intersection of the second row and second column.
If that is not the answer you expect, I suggest you edit your question, tag it also as google-spreadsheet (javascript custom functions are specific to that), and clarify the requirements. A spreadsheet example could be useful for us all to help.

Related

How to produce a n by n matrix in JavaScript

Write the following function:
generateInput(n: number): number[][]
This function should produce an n by n array of preferences for companies or candidates. The
input generated will be used for testing a given solution. Above, we have described only the
shapes of the inputs; you will have to infer the constraints we’ve left out. Make sure that your
function always generates random values as it will be helpful to test a given solution with a
broad spectrum of input.
function generateInput(n) {
let matrix = [];
for (let i = 0; i < n; ++i) {
matrix[i] = [];
for (let j = 0; j < n; ++j) {
matrix[i][j] = [];
}
}
}
I'm a newbie of learning JavaScript, so could someone please check whether my code produce a n by n matrix or not?
You can run this in a node environment, or in the browser console, or even in a snippet on StackOverflow. In your case the code is failing to return the matrix when completed. I added that line and called it with a few different values in the snippet below, so you can see what it returns.
function generateInput(n){
let matrix = [];
for(let i=0; i<n; ++i) {
matrix[i] = [];
for(let j=0; j<n; ++j) {
matrix[i][j] = [];
}
}
return matrix;
}
console.log(generateInput(1));
console.log(generateInput(2));
console.log(generateInput(3));
console.log(generateInput(4));
Yes, it produces a matrix with empty arrays. To get access to matrix variable from outside you need to return this value. See example below.
function generateInput(n){
let matrix = [];
for (let i=0; i<n; i++) {
matrix[i] = [];
for (let j=0; j<n; j++) {
matrix[i][j] = [];
}
}
return matrix; // here
}
const result = generateInput(5);
console.log(result);

How do i split up an array that holds an array?

Hello my fellow JS friends,
I am letting a user import a csv file (excel sheet) and i convert that into
an array. which has 472 rows and 87 columns in this case.
so my array looks like this:
and everything is separated by commas like a usual array.
The issue is I need to separate the array within the array and when i do that i get an array with the length of 9 million, which i think is wrong
vm.allTextLines = files.split(/\r\n|\n/);
var headers = vm.allTextLines[0].split(',');
vm.columnCount = headers.length;
vm.rowCount = vm.allTextLines.length - 1;
for (var i = 0; i < vm.allTextLines.length; i++) {
// split content based on comma
var data = vm.allTextLines[i].split(',');
if (data.length == headers.length) {
var tarr = [];
for (var j = 0; j < headers.length; j++) {
tarr.push(data[j]);
}
vm.lines.push(tarr);
}
}
//this is where i split the array that contains the csv
//data and put it into its own array I believe this is
//where the issue is.
for(var i=1;i<vm.allTextLines.length; i++){
vm.uniqueAll.push(vm.allTextLines[i].split(','));
for(var j=0; j < vm.uniqueAll.length; j++){
for(var r =0; r < vm.uniqueAll[j].length; r++){
vm.arrayOfValuesOfFile.push(vm.uniqueAll[j][r]);
}
}
}
If you can help me correct this for each I would appreciate it alot.
Thank you in advance guys!
I agree with you about the place of error, because it seems you nested the loop in a wrong way. Following a snippet where you can check what I mean.
i.e:
let vm = {
allTextLines:['h1,h2,h3','row1val1,row1val2,row1val3', 'row2val1,row2val2,row2val3'],
uniqueAll: [],
arrayOfValuesOfFile:[]
}
// Here you should not nest the loop
for(var i=1;i<vm.allTextLines.length; i++){
vm.uniqueAll.push(vm.allTextLines[i].split(','));
}
for(var j=0; j < vm.uniqueAll.length; j++){
for(var r =0; r < vm.uniqueAll[j].length; r++){
vm.arrayOfValuesOfFile.push(vm.uniqueAll[j][r]);
}
}
console.log('allTextLines', vm.allTextLines);
console.log('uniqueAll', vm.uniqueAll);
console.log('arrayOfValuesOfFile', vm.arrayOfValuesOfFile);
Of Course you could easily optimize the algorithm:
let vm = {
allTextLines:['h1,h2,h3','row1val1,row1val2,row1val3', 'row2val1,row2val2,row2val3'],
uniqueAll: [],
arrayOfValuesOfFile:[]
}
for(var i=1;i<vm.allTextLines.length; i++){
let currentLinesValue = vm.allTextLines[i].split(',');
vm.uniqueAll.push(currentLinesValue);
for(var r =0; r < currentLinesValue.length; r++){
vm.arrayOfValuesOfFile.push(currentLinesValue[r]);
}
}
console.log('allTextLines', vm.allTextLines);
console.log('uniqueAll', vm.uniqueAll);
console.log('arrayOfValuesOfFile', vm.arrayOfValuesOfFile);
First you should transform you bidimensional array into a one-dimension array.
var allTogether = []; // Array with all your CSV (no matter from which file it came from)
for (var i = 0; vm.allTextLines.length; i++) {
allTogether.push(vm.allTextLines[i]); // Gets the CSV line an adds to a one-dimension array
}
// Now you can iterate over the one-dimension array
for (var i = 0; allTogether.length; i++) {
var csvFields = allTogether[i].split(',');
// Here goes your code that works with the CSV fields.
}

Find if Array contains a user

I have a parse background job that contains a simple query.each for one class. This class has 2 Arrays field filled with objects.IDs. Inside this query, for every single object, i need to check if the objects.ID of the first Array are contained in the second Array.
Basically in a simple loop:
var j = 0;
for (var j = 0; j < firstArray.length; j++) {
if(firstArray[j] "isContainedIn" secondArray){
// my custom code
}
}
What i can't figure out is the function to use, if exist..Does javascript have a function like that or i need to make a nested loop to achieve my goal?
EDIT: i worked it out using indexOf but the solution proposed by Shqiptar didn't work so here is the one that actually works:
first Array name = usersEligibleToVote
second Array name = usersThatVoted
for (var j = 0; j < usersEligibleToVote.length; j++) {
if(usersThatVoted.indexOf(usersEligibleToVote[j]) === -1){
console.log("user.id "+usersEligibleToVote[j]+" needs to vote");
} else {
console.log("user.id "+usersEligibleToVote[j]+" has voted");
}
}
var j = 0;
for (var j = 0; j < firstArray.length; j++) {
if(firstArray[j].contains(secondArray))
{
// your custom code here
}
}
And then for checking if an object is the same :
var j = 0;
for (var j = 0; j < firstArray.length; j++) {
if(firstArray[j].indexOf(secondArray) != -1)
{
// your custom code here
}
}
I would process it through a simple jQuery and javascript for loop like so:
var arr1;
var arr2;
var i;
for(i = 0; i < arr1.length; i++) {
if ($.inArray(arr1[i], arr2) {
break; //do things here or what not
}
}

loop on Multiple array values

I am confused about how to iterate on multiple values.
for example : values.categories[0].num[0].entry[0].label;
Do I need to write three for loops in order to iterate through categories, num and entry.
Because categories[0] will always identify the 1st position, but am looking for generic categories[i].
Can you please help me out whether to write three for loops or better option is there to achieve.?
This is what I have tried:
var result = [];
for (var i = 0; i < categories.length; i++) {
var abc = categories[i].num;
for (var j = 0; j < abc.length; j++){
var def = num[i].entry;
}
for(var k = 0; k < def.length; k++){
var ghi = entry[i].label;
result.push(ghi)
console.log(result);
}
}
you can use the each function of jquery.
$.each(categories, function(ci, num) {
// This set the index of the array in ci and the value in num = categories[ci]
$.each(num, function(ni, entry) {
// etc ...
});
});
if you want it to stop the iteration you can return false inside the callback function.

Using .set on a filtered array of IDs in backbone

I used Underscore.js's _.filter to get an array of object ids like so:
var downstreamMeters = _.filter(that.collection.models, function(item) { return item.get("isdownstreammeter"); });
Now I want to set a certain attribute of each model in the array. I thought it would make sense to do this:
for (var i = 0; i < downstreamMeters.length; i++) {
var sum = 0;
inputMeters = downstreamMeters[i].get("inputmeters");
for (var i = 0; i < inputMeters.length; i++) {
var flow = parseFloat(that.collection.get(inputMeters[i]).get("adjustedflow"));
sum += flow;
}
downstreamMeters[i].set({incrementalflow: sum});
}
However, I get the error:
Uncaught TypeError: Cannot call method 'set' of undefined
I checked the downstreamMeters array and it has the right objects in it. What do I need to do to set the attribute for each model in the array?
Saying for(var i = 0; ...) is somewhat misleading. JavaScript hoists all var declarations up to the top of the closest scope and for loop doesn't create its own scope. The result is that this:
for (var i = 0; i < downstreamMeters.length; i++) {
var sum = 0;
inputMeters = downstreamMeters[i].get("inputmeters");
for (var i = 0; i < inputMeters.length; i++) {
var flow = parseFloat(that.collection.get(inputMeters[i]).get("adjustedflow"));
sum += flow;
}
downstreamMeters[i].set({incrementalflow: sum});
}
is the same as this:
var i, sum, flow;
for (i = 0; i < downstreamMeters.length; i++) {
sum = 0;
inputMeters = downstreamMeters[i].get("inputmeters");
for (i = 0; i < inputMeters.length; i++) {
flow = parseFloat(that.collection.get(inputMeters[i]).get("adjustedflow"));
sum += flow;
}
downstreamMeters[i].set({incrementalflow: sum});
}
Now you can see that you are using exactly the same i in the outer and inner loops. On the first run through the loop, i will be inputMeters.length when you say downstreamMeters[i].set(...). Apparently, inputMeters.length > downstreamMeters.length so you end up running off the end of downstreamMeters; if you try to access an element of an array that is past the array's end, you get undefined and there's your
Cannot call method 'set' of undefined.
error.
Nesting loops is fine but you should be using different variables:
var i, j, sum, inputMeters;
for (i = 0; i < downstreamMeters.length; i++) {
sum = 0;
inputMeters = downstreamMeters[i].get("inputmeters");
for (j = 0; j < inputMeters.length; j++)
sum += parseFloat(that.collection.get(inputMeters[j]).get("adjustedflow"));
downstreamMeters[i].set({incrementalflow: sum});
}

Categories

Resources