How do I split up an array in bits in AS3 - actionscript-3

I'm making a game which reads from an array to find out what to put where.
An example:
[1,1,2,
2,3,1,
3,3,1]
How do I make it so that the last row comes first and then the second row after and so on.
What I want:
[3,3,1,
2,3,1,
1,1,2]
thanks in advance!

You can use something like this:
// Written in JavaScript, but should work as is in AS3
var list = [1,1,2,
2,3,1,
3,3,1];
var rowLength = 3;
var rowCount = list.length / rowLength;
var rows = [];
for (i = 0; i < rowCount; ++i)
{
var offset = i * rowLength;
rows.push(list.slice(offset, offset + rowLength));
}
rows.reverse();
var result = [];
for (var j in rows)
{
result = result.concat(rows[j]);
}
console.log(result); // result = [3,3,1,
// 2,3,1,
// 1,1,2];

Related

More efficient way to format cells based on a given reference

I am creating a google sheet which contains fixtures and I would like to color all the cells featuring the fixtures which show how relatively easy/difficult the match is for a given team. This is my spreadsheet. The following is the code that I am currently using -
// Function to find the row number of a given fixture
function findRow(empName){
var ss=SpreadsheetApp.getActive();
//var fix = ss.getSheetByName('Fixtures');
var fdr = ss.getSheetByName('FDR');
var data = fdr.getDataRange().getValues();
for(var i = 0; i<data.length;i++){
if(data[i][1] == empName){ //[1] because column E
Logger.log((i+1))
return i+1;
}
}
}
// Function to color the given cell based on its fixture difficulty
function colorMeUp() {
var ss = SpreadsheetApp.getActive();
var fix = ss.getSheetByName('Fixtures');
var fdr = ss.getSheetByName('FDR');
for(var i = 4; i <= 23; i = i + 1){
for(var j = 3; j <= 40; j = j + 1){
var temp = fix.getRange(i,j).getValue(); // Find the fixture to color
var master = fix.getRange(i,2).getValue(); // Find the reference team
var rowNumMaster = findRow(master);
var rowNumTemp = findRow(temp);
if(rowNumTemp < 23){
rowNumMaster = rowNumMaster + 20;
}
var tempRating = fdr.getRange(rowNumTemp,4).getValue();
var masterRating = fdr.getRange(rowNumMaster,4).getValue();
var fixDiff = masterRating + (6-tempRating); // Calculate relative fixture difficulty
var rang = fdr.getRange(1+fixDiff,8).getBackground();
fix.getRange(i,j).setBackground(rang);
}
}
}
As you can see, this code uses the table given in the "FDR" sheet to assign a colour to each fixture given in the "Fixture" sheet. However, when I press the ugly blue button on the left side the process of it happening is painfully slow and it exceeded the maximum time. Is there any way to make this process go faster by tweaking this code/ using a different approach? I am very new to all this so don't really know what I can do to make this better/faster.
Try integrating if(data[i][1] == empName){ column two of data into a flatten array and then you can use indexOf instead of call a function twice in the center of a loop. So inotherword trash findRow and build it inside of colorMeUp
So something like this:
function colorMeUp() {
var ss = SpreadsheetApp.getActive();
var fix = ss.getSheetByName('Fixtures');
var fdr = ss.getSheetByName('FDR');
const sA = fdr.getRange(1,2,fdr.getLastRow()).getDisplayValues().flat();
for(var i = 4; i <= 23; i = i + 1){
for(var j = 3; j <= 40; j = j + 1){
var temp = fix.getRange(i,j).getValue(); // Find the fixture to color
var master = fix.getRange(i,2).getValue(); // Find the reference team
var rowNumMaster = sA.indexOf(master) + 1
var rowNumTemp = sA.indexOf(temp) + 1
if(rowNumTemp < 23){
rowNumMaster = rowNumMaster + 20;
}
var tempRating = fdr.getRange(rowNumTemp,4).getValue();
var masterRating = fdr.getRange(rowNumMaster,4).getValue();
var fixDiff = masterRating + (6-tempRating); // Calculate relative fixture difficulty
var rang = fdr.getRange(1+fixDiff,8).getBackground();
fix.getRange(i,j).setBackground(rang);
}
}
}
I threw this together rather quickly so it may not actually work but it should speed things up considerably using that approach. If you've done a few web apps then my guess is that you're a reasonable coder and should be able to integrate this into you code. Or it's possible that I'm totally FOS.
It would be really good to get rid of the getValue() in the loop in lieu of getValues() outside of the loop and use array indices to access the same data . Same with getbackground. I'd need to see your data to figure that out.
BTW I don't follow links to spreadsheets so giving me access to data involves post tables.'

Convert string range to float and return its max on GAS

I haven't been able to convert the array into float to get its max and add 0.1 to it and then return it in string format.
Any idea on what needs tweaking here?
function newVersion() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("ArquivoItens");
var range = sheet.getRange(2,1,sheet.getLastRow(),3).getValues();
var editarSheet = ss.getSheetByName('EditarItem');
var itemCode = editarSheet.getRange("W5").getValue();
var lastVersion = [];
var max = 0;
for (var i = 0; i < range.length; i++){
if(range[i].indexOf(itemCode) != -1){
lastVersion.push(parseFloat(range[i][2]));
}
}
max = Math.max(lastVersion);
return max; //to string
Logger.log(max);
}
Thanks for any light here.
Here is the working piece of code that does what the question says:
for (var i = 0; i < range.length; i++){
if(range[i].indexOf(itemCode) != -1){
lastVersion.push(parseFloat(range[i][2]));
}
}
max = Math.max.apply(null, lastVersion) + .1;
Logger.log(max.toFixed(1));
return max.toFixed(1);
}
If you want to apply Math.max() to an array, you need to expand the values of the array into the function's arguments
So:
max = Math.max(...lastVersion);
Read this for more information.
Also, return will finish your function execution, so any logs or other code you implement subsequently will be ignored.

How to pass data from one column to another one ?

I have a spreadsheet with multiple rows and columns. Two columns (column 3&4) are filled with text. I want to clean the text from this two columns and delete every specific characters (newlines, comma, exclamation point, quote,etc...). So I wrote the following script :
function testwoD() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var row_count = input.getLastRow()
var col_count = input.getLastColumn();
raw_data = input.getRange(1, 1,row_count,col_count).getValues()
temp3 = []
for (var i = 0; i < row_count; i++) {
var punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~\r\n|\n|\r]/g;
var spaceRE = /\s+/g;
temp3.push(raw_data[i][4].toString().replace(punctRE, '').replace(spaceRE, ' '));
}
temp4 = []
for (var i = 0; i < row_count; i++) {
var punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~\r\n|\n|\r]/g;
var spaceRE = /\s+/g;
temp4.push(raw_data[i][3].toString().replace(punctRE, '').replace(spaceRE, ' '));
}
var toAddArray3 = [];
for (i = 0; i < temp3.length; ++i){
toAddArray3.push([temp3[i]]);
}
var toAddArray4 = [];
for (i = 0; i < temp4.length; ++i){
toAddArray4.push([temp4[i]]);
}
output.getRange(1, col_count-13,row_count,1).setValues(toAddArray3);
output.getRange(1, col_count-14,row_count,1).setValues(toAddArray4);
}
It's working but It's very complicated and confusing. I made it step-by-step so even myself have some difficulties to really explain it.
Is there a way to significantly improve it ?
Best,
Simon.
DRY! - Do not repeat yourself.
Another popular idiom should be UMNF - Use map not for.
Putting everything into its own function encapsulates functionality and puts the focus on what you want to do with the data at each level rather than bookkeeping indices and subscripts.
function cleanColumns() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var raw_data = input.getDataRange().getValues();
var columnsToClean = [3,4];
function cleanText(t) {
var punctRE = /[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?#\[\]^_`{|}~\r\n|\n|\r]/g;
var spaceRE = /\s+/g;
return t.toString().replace(punctRE, "").replace(spaceRE, " ");
};
function cleanColumn(col) {
return raw_data
.map(function(row) {return row[col];})
.map(cleanText)
.map(function(row) {return [row];})
};
function cleanAndWrite(col) {
var data = cleanColumn(col);
output.getRange(1, col + 1, data.length, 1).setValues(data);
}
columnsToClean.forEach(cleanAndWrite);
}

Split some strings and pass them in two different columns.

I've the following situation :
Sheet 1 (input) :
www.url1.com?somestuff
www.url2.com?somestuff
www.url3.com?somestuff
www.url4.com?somestuff
Sheet 2 (expected output):
Col1 Col2
www.url1.com ?somestuff
www.url2.com ?somestuff
www.url3.com ?somestuff
www.url4.com ?somestuff
Here is what I've done until now :
function testwoD() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet11");
var row_count = input.getLastRow()
var col_count = input.getLastColumn();
raw_data = input.getRange(1, 1,row_count,col_count).getValues()
tempArr = [] // or new Array
for (var i = 0; i < row_count; i++) {
tempArr.push(raw_data[i][6].split("?")[0]);
tempArr.push(raw_data[i][6].split("?")[1]);
}
var toAddArray = [];
for (i = 0; i < tempArr.length; ++i){
toAddArray.push([tempArr[i]]);
}
Logger.log(tempArr)
output.getRange(1, 1,730,1).setValues(toAddArray);
}
And here is the result I have on Sheet2 :
www.url1.com
?somestuff
www.url2.com
?somestuff
www.url3.com
?somestuff
www.url4.com
?somestuff
How can I reach the expected output ? I've read a lot of questions about transposing array but couldn't find the answer that could help me solve my issue.
Thanks !
Instead of push and concat you can do this
tempArr = [] // or new Array
for (var i = 0; i < row_count; i++) {
tempArr[i] = []
tempArr[i][0] = raw_data[i][6].split("?")[0];
tempArr[i][1] = raw_data[i][6].split("?")[1];
}
or better still you just push the whole split array.
for (var i = 0; i < row_count; i++) {
tempArr.push(raw_data[i][6].split("?"))
}
The basic idea is to get the two columns in the array per row index. So when you do setValues it writes in two corresponding columns
Final code:
function testwoD() {
var input = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Raw_data");
var output = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet11");
var row_count = input.getLastRow()
var col_count = input.getLastColumn();
raw_data = input.getRange(1, 1,row_count,col_count).getValues()
tempArr = [] // or new Array
for (var i = 0; i < row_count; i++) {
tempArr[i] = []
tempArr[i][0] = raw_data[i][6].split("?")[0];
tempArr[i][1] = raw_data[i][6].split("?")[1];
}
// Not sure what this code is suppose to achieve? hence removed it
/*var toAddArray = [];
for (i = 0; i < tempArr.length; ++i){
toAddArray.push([tempArr[i]]);
}*/
Logger.log(tempArr)
// You can use setValues and get numof rows and columns using array length
output.getRange(1, 1,tempArr.length,tempArr[0].length).setValues(tempArr);
}
Hope that helps

Apps Script: Construct range of rows from array of row numbers

I have a list of row numbers in a spreadsheet which I need to change the background colour of. As the spreadsheet is quite large (10+ sheets, each with almost 5000 rows), I am trying to construct a range so I can batch set the background, as doing each row individually was taking over the max time of 6 minutes.
Here's the code I have:
// highlight required rows
var first = -1, last = -1;
for(var j = 0; j < rowNumsToHighlight.length; j++) {
if(first == -1) {
first = rowNumsToHighlight[j];
continue;
}
// if the current row number is one more than the previous, update last to be the current row number
if(rowNumsToHighlight[j] - 1 == rowNumsToHighlight[j - 1]) {
last = rowNumsToHighlight[j];
continue;
}
// otherwise the last row should be the previous one
else {
last = rowNumsToHighlight[j - 1];
}
var numRows = (last - first) + 1;
var range = sheet.getRange(first, 1, numRows, 4);
if(range.getBackground().toUpperCase() != highlightColour.toUpperCase()) {
range.setBackground(highlightColour);
}
first = -1;
last = -1;
}
rowNumsToHighlight is just an array that looks like: [205,270,271,272,278,279]. So, with that as an example, setBackground should be ran on row 205, on rows 270-272, and on 278-279.
I'm fairly sure the solution is simple, but just can't see it. Thanks for any help.
==== Updated Code ====
Based on Serge's code below, I made it more efficient again by reducing the number of getRange() calls made. Time is down from 78 to 54 seconds.
function updateColours(sheet, array, colour){
var columns = sheet.getLastColumn();
var rows = sheet.getLastRow();
var range = sheet.getRange(1, 1, rows, columns);
Logger.log("Resetting highlight on all rows...");
range.setBackground(null);
var backgrounds = range.getBackgrounds();
for(var n = 0; n < backgrounds.length; n++){
var rowIdx = n + 1;
if(array.indexOf(rowIdx) > -1){
for(var c = 0; c < columns; c++){
backgrounds[n][c] = colour;
}
}
}
Logger.log("Highlighting non-translated rows...");
range.setBackgrounds(backgrounds);
}
Maybe this one is faster(?) and built in a way that will make your work easier (function with arguments).
It writes only once to the sheet (or 2 if you clear colors before writing)...
use like below :
function testBG(){
updateColors(0,[7,8,9,18,19,23]);
}
function updateColors(sheetNum,array){
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheets()[sheetNum];
var columns = sh.getMaxColumns();
var range = sh.getRange(1,1,sh.getMaxRows(),columns);
sh.getRange(1,1,sh.getMaxRows(),columns).setBackground(null);// use this if you want to clear all colors before setting them
var backGrounds = range.getBackgrounds();// get all cells BG
for(var n=0;n<backGrounds.length;n++){
var rowIdx = n+1;
if(array.indexOf(rowIdx)>-1){
for(c=0;c<columns;c++){
backGrounds[n][c]="#F00";// if row number is in the array fill in red
}
}
}
sh.getRange(1,1,sh.getMaxRows(),columns).setBackgrounds(backGrounds);//update sheet in one call
}
test sheet in view only, make a copy to test.
This is how I would do it:
function createRanges() {
var rowNumsToHighlight = [5,7,8,9,18,19];
var arrayLength = rowNumsToHighlight.length;
var loopCounter = 0, thisNumberInArray=0, nextNumberInArray=0, crrentNmbrPlusOne=0;
var currentRangeBegin=0, numberOfRowsInRange=1;
currentRangeBegin = rowNumsToHighlight[0];
for(loopCounter=0; loopCounter < arrayLength; loopCounter+=1) {
thisNumberInArray = rowNumsToHighlight[loopCounter];
nextNumberInArray = rowNumsToHighlight[loopCounter+1];
crrentNmbrPlusOne = thisNumberInArray+1;
if (nextNumberInArray===undefined) {
workOnTheRange(currentRangeBegin, numberOfRowsInRange);
return;
};
if (nextNumberInArray!==crrentNmbrPlusOne) {
workOnTheRange(currentRangeBegin, numberOfRowsInRange);
numberOfRowsInRange = 1; //Reset to 1
currentRangeBegin = nextNumberInArray;
} else {
numberOfRowsInRange+=1;
};
};
};
function workOnTheRange(first,numRows) {
var range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet11').getRange(first, 1, numRows, 4);
range.setBackground("red");
};
I've tested the code and it works.