GoogleScript - convert arrays of different lengths into arrays of the same length - javascript

To be able to use setValues() instead of setValue on a high number of rows, I would like to know how can I convert all my arrays into arrays of the same length.
During a map function, I create one giant array that looks like this :
const myArray = [[Monday, Tuesday],[Monday,Tuesday,Wednesday],[Friday],[Monday,Friday],[Tuesday,Wednesday,Friday]] // And so on.
At the moment I use a setValue for each item of the array. The next step would be simply to use setValues(), and append an array but the problem is they are all of different lengths.
result.forEach(function(_,index){
currentSheet.getRange(1+index,5).setValue(result[index]);
});
That is going to do that for 600 lines and I will do it several times with other functions. I can live with it, but it seems like a waste. Is there a way to make the arrays homogenous (all arrays would be have a length of 3 elements, one or two being empty for example) an use one single setValues() instead ?
EDIT : the original map function to create the first array was requested. Here it is :
(Basically what it does is : it runs a map through a first array, look at the first element and go find in the source all the elements that have the same key and return the 9th and 10th elements of that array)
const result = UniquesDatas.map(uniqueRow =>
SourceDatas
.filter(row => row[0] === uniqueRow[0])
.map(row => [row[9]+" "+row[10]])
);
Thank you in advance,
Cedric

You can concat an array of empty elements of the remaining length.
const myArray = [['Monday', 'Tuesday'],['Monday','Tuesday','Wednesday'],['Friday'],['Monday','Friday'],['Tuesday','Wednesday','Friday']]
const res = myArray.map(x => x.concat(Array(3 - x.length)));
console.log(res);
As suggested by Kinglish, to get the length of the inner array with the most elements, use Math.max(...myArray.map(x=>x.length)), which will work for the more general case.

Related

Filter an array from another array of elements and return specific positions

I'm finally learning better methods for my JS. I'm trying to find a way to go faster than I do so far :
In my code, I have two arrays :
one with unique keys in first position
one with those keys in first position but not unique. There are multiple entries with a certain value I want to filter.
The thing is I don't want to filter everything that is in the second array. I want to select some positions, like item[1]+item[5]+item[6]. What I do works, but I wonder if there isn't a faster way to do it ?
for (let i=0;i<firstArrayOfUniques.length;i++){
const findRef = secondArrayOfMultiple
.filter(item => item[0]==firstArrayOfUniques[i][0]);
// Afterwards, I redo a map and select only the second element,
//then I join the multiple answers
// Is there a way to do all that in the first filter?
const refSliced = findRef.map(x=>x[1]);
const refJoin = refSliced.join(" - ");
canevasSheet.getRange(1+i,1).setValue(refJoin);
}
The script snippet you quote will spend almost all of its running time calling the Range.setValue() method. It gets called separately for every data row. Use Range.setValues() instead, and call it just once, like this:
function moot(firstArrayOfUniques, secondArrayOfMultiple) {
const result = firstArrayOfUniques.map(uniqueRow =>
secondArrayOfMultiple
.filter(row => row[0] === uniqueRow[0])
.map(row => row[1])
.join(' - '));
canevasSheet.getRange(1, 1, result.length, result[0].length).setValues(result);
}
See Apps Script best practices.

Concat 2 arrays but one of them contains subarray

I have 2 arrays. The first one is simple:
The second one contains sub-arrays:
and every element of the sub-arrays should be concated to the first one so they can form one array of same elements.
Here is sandbox:
https://codesandbox.io/s/smoosh-dust-kpg5l?file=/src/App.js
Arrays are data1 and data2. Final data is how it should look like. I tried several loops to form it but unsuccessfully.
Array#flatMap to the rescue:
const newArr = [...data1, ...data2.flatMap((el) => el)];

How to push data to specific sub-array in an empty 2-dimensional array

I'm trying to setup a 2-d array, which should receive values at specific sub-arrays. I created my array with:
myArray= Array(100).fill([])
Now, let's say I want to push a value to say sub-array number 40
I'm doing this like that:
myArray[40].push("myValue")
I would expect the value to be pushed only to the myArray[40] instead it is pushed as the first element of every of the hundred sub-arrays.
I searched for the solution for quite some time, but I still have no idea what I'm doing wrong. Please help.
fill will push the same value to each element, not a copy of it. That's fine when it's a number or string or something else immutable. But now each copy is a reference to the same object.
There are a number of ways to fix this. Here's one (switched to ten elements for demonstration):
const myArray = [...Array(10)].map((_, i) => [])
myArray[4].push('myValue')
console.log(myArray)

Use Array.map on an 2-dimensional Array

So I have a 2-dimensional Array and want to use a "randomBool" function on each of the elements of the elements in the array.
The "randomBool" function just returns a random boolean:
const randomBool = () => Boolean(Math.round(Math.random()));
this would be the 2-dimensional Array, that I would input:
var test = [
["just","some","random","text"],
[1412,"test",1278391]
]
There is a working for-loop nested in a for-loop:
for (let el of test){
for(let i in el){
el[i] = randomBool();
}
}
I tried this:
test.forEach(el => el.map(el2 => randomBool()));
But it didn't work. Why?
You need to use two nested maps.
const randomBools = test.map(outer => outer.map(inner => randomBool()))
forEach is usually intended to iterate over each item in order to perform some kind of side effect without returning anything and without mutating the original array. For example, printing each item to the console.
map, on the other hand, is intended to take an array and return a new array of the same size, with the values transformed in some way, without mutating the original array. For example, uppercase all the words in a list.
Since you want to return a new 2 dimensional from your existing 2 dimension array with some data transformed, you need to nest your map functions. This will map first over the rows (outer), then the columns (inner). The results of the inner maps will be collected into the outer map and you'll be left with a 2 dimensional array with your new values, all without modifying the original array.

Javascript slice isn't giving me correct array length values

Why does it say length 1 instead of 4?
The following is what I'm trying to push and slice. I try and append items.image_urls and slice them into 5 each.
items.image_urls is my dictionary array.
var final_push = []
final_push.push(items.image_urls.splice(0,5))
console.log(final_push.length)## gives me 1...?
var index = 0
final_push.forEach(function(results){
index++ ##this gives me one. I would need 1,2,3,4,5,1,2,3,4,5. Somehting along that.
}
items.image_urls looks like this:
It's an iteration of arrays with image urls.
In your example items.image_urls.splice(0,5) returns an array of items removed from items.image_urls. When you call final_push.push(items.image_urls.splice(0,5));, this whole array is pushed as one item to the final_push array, so it now looks like [["url1", "url2", "url3", "url4", "url5"]] (2-dimensional array). You can access this whole array by calling final_push[some_index].
But what you want instead is to add every element of items.image_urls.splice(0,5) to the final_push. You can use a spread operator to achieve this:
final_push.push(...items.image_urls.splice(0,5));
Spread syntax allows an iterable such as an array expression or string
to be expanded in places where zero or more arguments (for function
calls) or elements (for array literals) are expected
This is exactly our case, because push() expects one or more arguments:
arr.push(element1[, ...[, elementN]])
And here is an example:
let items = {
image_urls: ["url1", "url2", "url3", "url4", "url5", "url6", "url7", "url8", "url9", "url10"]
};
let final_push = [];
final_push.push(...items.image_urls.splice(0,5));
console.log(final_push.length);
console.log(JSON.stringify(final_push));
console.log(JSON.stringify(items.image_urls));
Note: do not confuse Array.prototype.slice() with Array.prototype.splice() - the first one returns a shallow copy of a portion of an array into a new array object while the second changes the contents of an array by removing existing elements and/or adding new elements and returns an array containing the deleted elements.
That seems to be a nested array. So if you would access index 0, and then work on that array like below it will probably work:
console.log(final_push[0].length); //should print 4
The author is mixing up splice and slice. Probably a typo :)
You start at the beginning (0) and then delete 5 items.

Categories

Resources