I have a two-dimensional array in Google apps script that contains arrays of different lengths. I would like to set the values of the array in a spreadsheet. However, because the arrays inside it are different lengths, I receive an error that essentially says the range and the array height don't line up. I've listed an example of the structure of the array below.
I can make it work if I add empty values to each individual array so that they all match the length of the longest array. This seems like a workaround though. Is there another way that I can set the values of the two-dimensional array?
var array = [
[a],
[b,c],
[d,e],
[],
[f,g,h,i],
[],
[j,k],
]
No, you cannot. The dimensions must match.
What you can do if you have few "rows" with great length difference, is to set each row on it's own.
for( var i = 0; i < array.length; ++i )
sheet.getRange(i+1, 1, 1, array[i].length).setValues([array[i]]);
But that's just another workaround. But working on your array to make all lengths match and do a single setValues will probably perform better.
In case your real array has many rows, individual writes will be expensive. Redimensioning each row array is fairly straightforward due to the way js handles arrays. A pattern similar to one i use is:
function myFunction() {
var array = [
[1],
[2,2],
[3,5],
[],
[0,0,0,0],
[],
[0,0],
];
// get length of the longest row
var max = array
.slice(0)
.sort(function (a,b) {
return ( (a.length !== b.length) ? 1 : 0 );
})[0].length;
// arrays are zero indexed
var maxi = max-1;
// insert a pointer at max index if none exists
array = array
.map(function (a){
a[maxi] = a[maxi] || "";
return a;
});
Logger.log(array);
}
Related
I have two arrays, one with strings of large numbers and the other with the sums of the large numbers added together, is there any way where I can have the two arrays correspond with each other? Like to make location [2] in the first array correspond with the same location in the second array. More specifically, I originally establish the array of large numbers, and I've written a function that creates the second array giving me the sums of each numeral in the large numbers (ex. 123456789 in the first array would be 45 in the second array), but I need to be able to link the two arrays because the first array needs to work with any number of strings of numbers. (sorry if this is confusing; I'm just a little out of my depth on this.)
Here is the code I'm working on:
var theArray = ["585-777-7279", "922-901-8934", "112-211-4857", "994-934-9989"];
var plsWork = function() {
var theArrayTwo = theArray.join().replace(/-/g, "");
var theArrayThree = theArrayTwo.split(",").map(Number);
var phoneSum = theArrayThree.map(function (a) {
return Array.prototype.slice.call(a.toString()).map(Number).reduce(function(b,c) {
return b + c;
});
})
phoneSum.sort().reverse();
console.log(phoneSum);
};
Basically, I just want to know if there's a way that I can get the two arrays (the original and the one created in the function) to correspond. Ideally, I would like to be able to have it where I can show that the smallest sum corresponds with the number from the first array.
If you already have the two arrays, the best way to relate one to another would be to create an array of objects as suggested by #webdeb.
If instead you have the array of large numbers and then all you want is to create a second array that in each index contains the sum of all the digits of the number in the first array, than I would use the following code:
var large_numbers = [1234, 2345, 3456];
function sumDigits(number) {
var digitsArray = [],
string = number.toString(); // convert number to string
for (let i = 0; i < string.length; i++) {
// push the numbers to a temporary array so that
// I can sum them one by one later
digitsArray.push(parseInt(string[i], 10));
}
// return the sum of all the elements of the digitsArray
return tempArray.reduce(function(prev, curr) {
return prev + curr;
})
}
var sumsArray = large_numbers.map(sumDigits); // -> [10, 14, 18]
The sumsArray contains in the sum of all the digits of the number in the large numbers array in the same index.
I have pre-existing two arrays on the webpage that I need to customize, one with strings and other with corresponding id's. I need to replaces the strings in array1 based on the information I get using array2.
I have problem looping through array1 as it only gives me length = 1 in all cases.Why so? Is there any better way to accomplish this task? I will appreciate any help I can get. Thanks
var arr1= [[ "Khyle", "Marlen", "Jose"]];
var arr2= [[ "51", "69","22"]];
//replace extra square brackets
var str = arr2.replace((/[\[[']+/g,'[');
str= str.replace((/[\]]']+/g,']');
var length = str.length, element = null;
for (var i = 0; i < length; i++) {
element = str[i];
// Ajax call to get the info and load in arr1[i]
arr1[i] = ajax-str
}
You have got an array inside an array.
This is why the array length is 1.
It should be:
var arr1= [ "Khyle", "Marlen", "Jose"];
var arr2= [ "51", "69","22"];
or you could write arr1 = arr1.pop() to get the array outside of array.
This is the reason why:
var arr1= [[ "Khyle", "Marlen", "Jose"]];
That dimensions out to the equivalent of arr1[0][strings], or 2 dimensions.
so, element 0 will always have a length of 1.
The reason you're getting an array length of 1 is because you're using double brackets, and you only need one pair of brackets to define an array in Javascript.
Because of that, you're actually creating an array that holds a single element: another array which holds the strings "Khyle", "Marlen" and "Jose".
I have two 1D arrays and I want to fill them with 10 unique random x,y values in Processing.
For example:
x y
- -
3, 9
2, 4
6, 2
7, 5
My arrays are:
Table1 for the X values and
Table2 for the Y values.
My issue is if the number 3,9 exists already I don't want 9,3 to be stored in the arrays.
I can identify when x,y value (or y,x) already exists but once I replace it I cannot check if the new generated random number exist in the previous indexes.
This is what I have tried so far. However if 3 values aldready exists, the arrays Table1 and Table2 will store only 7 values instead of 10.
for (int i=0; i<10; i++) {
x=(int)random(6);
y=(int)random(6);
if ((Table1[i] != x && Table2[i] != y) || (Table1[i] != y && Table2[i] != x))
{
Table1[i] = x;
Table2[i] = y;
}
Any ideas how to control that?
I can think about only two ways of achieving it, and none is ideal.
Check if the numbers you generated already exists, and if it's the case, generate anothers until you get a unique combination. It could be expensive with a small range of possibilities, because it's random, and if you're very unlucky you could even end in an infinite loop...
Create an array containing every possible combination. Then, instead of generating random numbers, you'll generate a random index into this array (an integer in [0;array.length[). After that, you'll have to remove the choosen combination from the array (that way it won't be available for the next loop), and the inverse of it (if you picked (9;3), you have to remove (9;3) AND (3;9)).
I have this code that might help you,
first declare your arrays :
var a = [];
var b = [];
then you can call a function that does everything for you
fill(a,b)
The definition of this function should be something like this :
function fill(a, b) {
var arr = [];
while(arr.length<10) {
var pair = randomPair();
if (arr.indexOf(pair.join(','))==-1 || arr.indexOf(pair.reverse().join(','))==-1) {
a.push(pair[0]);
b.push(pair[1]);
arr.push(pair.join(','));
}
}
}
then the defintion of other used function is :
function randomPair () {
return [ parseInt(Math.random()*7) , parseInt(Math.random()*7) ]
}
so, obviously, the randomPair function returns 2 values x and y. the fill function tests if the pair already exists or not in normal order or reversed order. if not it's added both a, and b which are references to your main arrays;
I see no other option as to walk to the whole arrays again to check if they contains your new generated value(s).
How do I create an empty 2D array in Javascript (without knowing how many rows or columns there will be in the new array)?
If it's a simple array var newArray = new Array(); I can assign as many elements as I want. But what about a 2D array? Can I create one without specifying the numbers of rows and columns? and how do I access the elements afterwards (myArray[0][1] or myArray[0,1])?
You can create a 6 x 6 empty array like this:
var myGrid = [...Array(6)].map(e => Array(6));
Array(6) generates an array with length = 6 and full of undefined values.
We map that array to another array full of undefined values.
In the end, we get a 6x6 grid full of undefined positions.
If you need to initialize the grid with a default value:
var value = 'foo'; // by default
var myGrid = [...Array(6)].map(e => Array(6).fill(value));
Now you have a 6 x 6 grid full of 'foo'.
Yes you can create an empty array and then push data into it. There is no need to define the length first in JavaScript. Check out jsFiddle Live Demo
Define:
const arr = [[],[]];
Push data:
arr[0][2] = 'Hi Mr.A';
arr[1][3] = 'Hi Mr.B';
Read data:
alert(arr[0][2]);
alert(arr[1][3]);
Update:
Here is also a video recommended by Brady Dowling:
Create a 2D array: ([https://www.youtube.com/watch?v=tMeDkp1J2OM][2])
There are no two dimensional arrays in Javascript.
To accomplish the effect of a two dimensional array, you use an array of arrays, also known as a jagged array (because the inner arrays can have different length).
An empty jagged array is created just like any other empty array:
var myArray = new Array();
You can also use an empty array literal:
var myArray = [];
To put any items in the jagged array, you first have to put inner arrays in it, for example like this:
myArray.push([]);
myArray[0][0] = 'hello';
You can also create an array that contains a number of empty arrays from start:
var myArray = [[],[],[]];
That gives you a jagged array without any items, but which is prepared with three inner arrays.
As it's an array of arrays, you access the items using myArray[0][1].
Say you wanted to make a 2d array (i.e. matrix) that's 100x100, you can do it in one line, like this:
var 2darray = new Array(100).fill(null).map(()=>new Array(100).fill(null));
This will create a 100x100 matrix of NULL's.
Replace the 100x100 with whatever dimensions you want, and the null's with whatever is your prefered default value, or blank for undefined.
You can use a simple for loop to create an array of the approximate size and then push more rows if need be.
const arr = [];
const n = 7;
const m = 5;
for (let i = 0; i < n; i++) {
arr.push(new Array(m).fill(0));
}
const arr = [];
const n = 7;
const m = 5;
for (let i = 0; i < n; i++) {
arr.push(new Array(m).fill(0));
}
console.log(arr);
var myArray = [
["cats","dogs","monkeys","horses"],
["apples","oranges","pears","bananas"]
];
document.write(myArray[0][2]) //returns "monkeys"
Two things:
1) The array length property improperly reports the array length if called after the var myArray = [[],[]]; statement. Technically, since the empty arrays are defined, they are getting counted by the length property, but in the spirit of the length property it really should return 0, because no non-empty elements have been added to any of the arrays.
A minimum work around is to use two nested for( in ) loops, one for the 1st array and one for the 2nd array, and to count the non-undefined elements.
2) Extending Siamak A.Motlagh example and adding a arr([2][4]) = 'Hi Mr.C'; assignment fails with an "Uncaught TypeError: Cannot set property '4' of undefined" error.
See the jsFiddle: http://jsfiddle.net/howardb1/zq8oL2ds/
Here is a copy of that code:
var arr = [[],[]];
alert( arr.length ); // wrong!
var c = 0;
for( var i in arr )
for( var j in arr[ i ] )
if( arr[ i ][ j ] != undefined )
++c;
alert( c ); // correct
arr[0][2] = 'Hi Mr.A';
alert(arr[0][2]);
arr[1][3] = 'Hi Mr.B';
alert(arr[1][3]);
arr[2][4] = 'Hi Mr.C'; // At this point I'm getting VM558:62 Uncaught TypeError: Cannot set property '4' of undefined
alert(arr[2][4]);
var c = 0;
for( var i in arr )
for( var j in arr[ i ] )
if( arr[ i ][ j ] != undefined )
++c;
alert( c );
Why does the third assignment fail? What about the [[],[]] creation statement told it that the first array was valid for 0 and 1, but not 2 or that 2 and 3 were ok for the second array, but not 4?
Most importantly, how would I define an Array in an Array that could hold date objects in the first and second arrays. I'm using the jQuery-UI DatePicker, which expects an array of dates, as in date objects, which I've extended to use a second date array to contain date objects that contain times so I can keep track of multiple dates, and multiple times per day.
Thanks.
The functions I use
function get_empty_2d_array(numRows, numColumnns) {
return [...Array(numRows)].map(e => Array(numColumnns));
}
function get_2d_array_filled(numRows, numColumnns, fillValue) {
return [...Array(numRows)].map(e => Array(numColumnns).fill(fillValue));
}
This also works as an expression:
var twoDarr= new Array(desiredLength);
for (i=0;i<twoDarr.length;i++) {twoDarr[i]=[];}
I don't know how it pars in terms of performance with the rest of the answers here, if you have a clue let me know in the comments.
If you don't know the length of the array beforehand pls have in mind that you can use either push([]), or splice() if you want to push/remove/replace a new element in place of an existing one.
const grid = new Array(n).fill(new Array(n))
I'm trying to sort some xml into different arrays and I'm a bit stuck on how to go about this.
Here is the xml: http://pastebin.ca/1754892
I'm using this xpath expression to get every "series" element that contains at least one "item" child node.
var ceerez = theXML.evaluate( '//series[item]' ,theXML, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null );
then I'm iterating over the result and putting the elements in a regular array:
var newArr=[];
for (var m = 0; m < ceerez.snapshotLength; m++){
newArr.push(ceerez.snapshotItem(m));
}
so what I would like to do next is to map and sort the elements in the newArr array into new arrays for each different sort.
I want to have one array that is numerically sorted by the "pub" attribute (as numbers) for each series element.
One array that is sorted alphabetically for each "title" child element's text.
One array that is sorted by date for each "item" child element.
I know how to do this with the sort() method, but I cant figure out how to do it from within the map() method so that I can make it into a new array.
var a2z1 = newArr.map(function(item){
item
.sort(function(a,b) {
return a.firstElementChild.textContent.toLowerCase().replace(/[^a-z,0-9]/gm, '') < b.firstElementChild.textContent.toLowerCase().replace(/[^a-z,0-9]/gm, '') ? -1 : 1;
});
);
(a.firstElementChild) would be the "title" element.
Make two other copies of the array (or three, if you don't want to use the original) and, using the sort method, sort each array (in place) by the criteria you specified.
Something like:
var copy1 = newArr.slice(0);
var copy2 = newArr.slice(0);
var copy3 = newArr.slice(0);
copy1.sort(function (a, b) {
// sort logic
});
copy2.sort(function (a, b) {
// sort logic
});
copy3.sort(function (a, b) {
// sort logic
});