Problem with create list using for loop in Javascript - javascript

I'm trying to crate a code that will count number of images I have and then will create a list with the number of images (for example, if I have 5 images, I'll get this :
[0,1,2,3,4].
My code runs and I think it creates a list that is empty:
This is my code (I have tried to put only the relevant part):
//First I filter my image collection according to the number of pixels each image has
//Filter according to number of pixels
var ndviWithCount = withNDVI.map(function(image){
var countpixels = ee.Number(image.reduceRegion({
reducer: ee.Reducer.count(),
geometry: geometry,
crs: 'EPSG:4326',
scale: 30,
}).get('NDVI'));
return image.set('count', countpixels);
});
print(ndviWithCount, 'ndviWithCount');
//Here I count what is the maximum number of pixels that image has and then I create new collection with //only "big images"
var max = ndviWithCount.reduceColumns(ee.Reducer.max(), ["count"]);
print(max.get('max'));
var max_pix=max.get('max');
//filter between a range
var filter = ndviWithCount.filter(ee.Filter.rangeContains(
'count', max_pix, max_pix));
print(filter, 'filtered');
//Here I try to grab the number of images so I can create a list
var num_images=filter.size();
//creating the list of images
var listOfImages =(filter.toList(filter.size()));
//Here is the loop that diesn't work
//I have tried to determine i=0, and then that it will iterate untill i is equal to the number of images
//I try to say, i=0, so add 1 and the nadd it to my list.
for (i = 0; i < num_images; i++) {
var listOfNumbers=[];
i=i.add(1);
listOfNumbers.push(i);
}
my end goal is to have list that contains nmbers from 0 or 1 to the number of images I have.

for (i = 0; i < num_images; i++) {
var listOfNumbers=[];
i=i.add(1);
listOfNumbers.push(i);
}
You are initiating the array inside the for loop which isn't what you intend. I'm also not sure what i = i.add(1) is supposed to be. May be helpful to check out info on for loops.
let listOfNumbers = [];
for (let i = 0; i < num_images; i++) {
listOfNumbers.push(i);
}

I found the solution. The reason for the error is because of the GEE envorinment.
This code works:
var serverList = ee.List.sequence(0,NumberOfImages.subtract(1));
serverList = serverList.map(function(n) {
return ee.Number(n).add(1);
});
print(serverList);

Related

Google Apps Script - XML Parser - Regex

I am using a Google Apps Script that pulls the content from a feed in a sheet.
This is the code that I'm using:
function processXML(FeedURL,sheetsFileDestinationURL,rawPasteSheetName,OPT_childNamesArray,OPT_Namespace){
var OPT_childNamesArray = ["link"]; // get only item url from the feed
var GoogleSheetsFile = SpreadsheetApp.openByUrl(sheetsFileDestinationURL);
var GoogleSheetsPastePage = GoogleSheetsFile.getSheetByName(rawPasteSheetName);
if (OPT_childNamesArray){
GoogleSheetsPastePage.getDataRange().offset(1,0).clearContent(); // get all filled cells, omitting the header row, and clear content
}
else {
GoogleSheetsPastePage.getDataRange().offset(0,0).clearContent(); // get all filled cells, INCLUDING the header row, and clear content
}
// Generate 2d/md array / rows export based on requested columns and feed
var exportRows = []; // hold all the rows that are generated to be pasted into the sheet
var XMLFeedURL = FeedURL;
var feedContent = UrlFetchApp.fetch(XMLFeedURL).getContentText(); // get the full feed content
var feedItems = XmlService.parse(feedContent).getRootElement().getChild('channel').getChildren('item'); // get all items in the feed
for (var x=0; x<feedItems.length; x++){
// Iterate through items in the XML/RSS feed
var currentFeedItem = feedItems[x];
var singleItemArray = []; // use to hold all the values for this single item/row
// Parse for specific children (requires names and namespace)
if (OPT_childNamesArray){
for (var y=0; y<OPT_childNamesArray.length; y++){
// Iterate through requested children by name and fill rows
var currentChildName = OPT_childNamesArray[y];
if (OPT_Namespace){
if (currentFeedItem.getChild(OPT_childNamesArray[y],OPT_Namespace)){
singleItemArray.push(currentFeedItem.getChildText(OPT_childNamesArray[y],OPT_Namespace));
}
else {
singleItemArray.push("null");
}
}
else {
if (currentFeedItem.getChild(OPT_childNamesArray[y])){
singleItemArray.push(currentFeedItem.getChildText(OPT_childNamesArray[y]));
}
else {
singleItemArray.push("null");
}
}
}
exportRows.push(singleItemArray);
}
// Parse for ALL children, does not require knowing names or namespace
else if (!OPT_childNamesArray){
var allChildren = currentFeedItem.getChildren();
if (x == 0){
// if looking at first item, create a header row first with column headings
var headerRow = [];
for (var h=0; h<allChildren.length; h++){
headerRow.push(allChildren[h].getName());
}
exportRows.push(headerRow);
}
for (var c=0; c<allChildren.length; c++){
singleItemArray.push(allChildren[c].getText());
}
exportRows.push(singleItemArray);
}
}
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
}
else if (!OPT_childNamesArray){
var maxRangeLength = 0;
var currentRowIndex = 1;
for (var x = 0; x<exportRows.length; x++){
if (exportRows[x].length > maxRangeLength){
maxRangeLength = exportRows[x].length;
}
GoogleSheetsPastePage.getRange(currentRowIndex,1,1,exportRows[x].length).setValues([exportRows[x]]);
currentRowIndex++;
}
}
}
My problem is this:
When I run this code I get:
https://url/115-396/
https://url/115-396/
https://url/115-396/
I need to remove "115-396/".
So I tryed to add this code but didn't work:
...
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
for (var k = 0; k < exportRows.length; k++) {
var re = '115-396/'
var replacingItem = '';
var URL = exportRows[0].toString().replace(re, replacingItem);
}
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValue(URL);
}
else if (!OPT_childNamesArray){
...
Edit after #Yuri reply:
// Paste the generated md array export into the spreadsheet
if (OPT_childNamesArray){
for ( k=0; k < exportRows[0].length; k++) {
var re = '115-396/'
var replacingItem = '';
exportRows[0][k] = exportRows[0][k].toString().replace(re, replacingItem);
}
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
}
result:
https://url/
https://url/115-396/
https://url/115-396/
Basically, the regex is applied only to the first url.
How I can make that the regex is applied to all the url's?
Any help?
Thanks
You are using a for to iterate thru the exportRow array, but later on, you're not using the k iterator inside the for.
Then, you are not accessing the exportRows array, only the first position:
var URL = exportRows[0].toString().replace(re, replacingItem);
Shouldn't be?
var URL = exportRows[k].toString().replace(re, replacingItem);
In that case, it won't work, because URL it's not an array, so by doing this you are only saving the last assignation produced on the for iterator on the URL, I believe you are trying to do the following:
for ( k=0; k < exportRows.length; k++) {
var re = '115-396/'
var replacingItem = '';
exportRows[k] = exportRows[k].toString().replace(re, replacingItem);
}
And you'll have exportRows as an array of the desired url's without the 115-396 extensions.
Now you can place this on the spreadsheet with setValue as you were doing, but setValue is for strings, integers, etc, and not for arrays. For arrays you have setValues()
GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length).setValues(exportRows);
But, then, the range of exportRows should match the range of your getRange selection, which I'm not sure it's happening.
Just to clarify it, exportRows.length is the length of the array, and exportRows[1] is the length of the string/url stored on the position 1 of the array.
Hope this helps, the question is not really clear neither the intentions, provide more info if still not working.
How to know the size of the range you're getting?
var myrange = GoogleSheetsPastePage.getRange(2,1,exportRows.length,exportRows[1].length)
Logger.log(myrange.getNumRows());
Logger.log(myrange.getNumColumns());
You'll be able to know the range you have on getRange and make it match with the exportRows size.
Make sure to check the attached documentation, and in case you have more doubts please open a new question related to it.

Creating an multidimensional array of array objects

I have a multidimensional array created by taking data from a google spreadsheet. I am attempting to seperate out the data based on results in a specific column. For example:
var j = {
["Mine", "House"],
["Your", "House"],
["his", "apt"]
}
Given that we want to seperate by column 2. We should get in theory:
var new = {
[["Mine", "House"] , ["Your", "House"]],
[["his", "apt"]]
}
Two entries being a house, and 1 being an apartment. I am haveing a huge issue with treating each entry as its own obj. Assuming it is even possible. I guess we would access specific parts of each object like so, new[0][1][1]? This obviously shouldnt work like this. Is there another way to seperate the entries in the way I am attempting? As it stands right now, I believe my code is just creating the same number of rows as in the original data.
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.insertSheet("Report");
var data_sheet =spreadsheet.getSheetByName("Data");
var genCounsel_data = data_sheet.getRange(240, 1, 96, 7).getValues(); //get genCounseling data
var report_sheet = spreadsheet.getSheetByName("Report");
//setup key values for columns in report sheet
report_sheet.appendRow(["Student Service", "Unit Student Service Outcome", "Indicators Data Sources", "How indicator was measured", "Benchmark Data", "Assigned to do Assessment", "Email"])
//seperate out by SS outcomes
var genCounselDataByOutcomes = new Array(new Array()); //all responses for each outcome, also parrellel
var outcomes_freq = new Array(); //parrellel arrays
var found = false;
//get services and frequency;
for(var i=0; i<genCounsel_data.length; ++i){
genCounsel_data[i][OUTCOMES_COL].toString().toLowerCase();
for(var j=0; j<genCounselDataByOutcomes.length && !found; ++j){
if(genCounselDataByOutcomes[j][OUTCOMES_COL] == genCounsel_data[i][OUTCOMES_COL]){
genCounselDataByOutcomes[j].push(genCounsel_data[i]); //ADD to row with same outcomes
++outcomes_freq[j]; //update amount of entries in said outcome
found = true;
}
}
if(found == false){
genCounselDataByOutcomes.push(new Array);
genCounselDataByOutcomes[genCounselDataByOutcomes.length-1].push([genCounsel_data[i]]);
outcomes_freq.push(1);
}
else
found = false;
}
for(var i=0; i<outcomes_freq.length;++i)
Logger.log(outcomes_freq[i]);
//for each outcome select a random one and move entire row to sheet;
for(var i=0; i<genCounselDataByOutcomes.length; ++i){
Logger.log(genCounselDataByOutcomes[i]);
}
QUESTION:
How can I seperate my data as multiple objects in a row of an array and be able to access specific components of each entry as shown in my example above? If this is not exactly possible in this way, is there another solution to this issue?
First of all, your j and new (which by the way is not a valid var name) need a key if they are objects or to be used as array, like below:
var j = [
["Mine", "House"],
["Your", "House"],
["his", "apt"]
];
var newVar = [
[["Mine", "House"] , ["Your", "House"]],
[["his", "apt"]]
];
That said and fixed, you can iterate over your array of arrays and use the column you want to use as filter to get the unique values to be used to group the final result.
Here is the final result:
var j = [
["Mine", "House"],
["Your", "House"],
["his", "apt"]
];
var uniqueValues = [];
var indexColumn = 1; //Here you specify the column you want to use to filter/group the elements from j
j.forEach(function(element){
if(!uniqueValues.includes(element[indexColumn])){
uniqueValues.push(element[indexColumn]);
}
});
//Now you use the `uniqueValues` to filter the `j` array and generate the `groupedArrays` array, which is the one you are looking for:
var groupedArrays = [];
uniqueValues.forEach(function(uniqueValue){
groupedArrays.push(j.filter(function(element){
return element[indexColumn] === uniqueValue;
}));
});
console.log(groupedArrays);
I hope this helps you.
Good luck.

JSON for-loop that ignores blank sub arrays

I am using p5 loadJSON to import data, the data gives an array with so many records and sub-arrays.
For example, data.records[i].form_values["94d5"] gives me a name.
I am currently using a for loop to go through data.records.length and give me an array of some key pieces of data relative to each record I want to see.
Problem:
I want to loop through the records and get the value of:
data.records[i].form_values["94d5"].choice_values["0"], but some records don't have form_values["94d5"], for example. I just want to skip empty sections (leave undefined like empty items) insted i get an error that choice_values is undefined.
My loop is:
function gotData(data){
var i = 0;
var statusFind = data.records[i].status;
for(i = 0; i < data.records.length; i++) {
var returned = [data.records[i].form_values["6f71"], data.records[i].form_values.b059, data.records[i].form_values["94d5"], data.records[i].form_values.b62d, data.records[i].form_values["3493"].choice_values["0"], data.records[i].status, data.records[i].form_values.af80];
for (j = 0; j < returned.length; returned++){
if (returned[j] == searchKey) {
var result = [returned[0], returned[1], returned[2], returned[3], returned[4], returned[5], returned[6]];
array.push(result);
write();
}
}
}
}

Looping through numbered html tag id's

I'm having an issue where I am not able to loop through the id's of multiple canvas tags which I have created to edit various pixel data. All the canvases have id's ranging from 0 - n. But when the id's are created, the numbers are turned into strings.
So, if I create a loop which iterates through the numbers which correspond to the id's of the tags, how do I make it so the .getElementById(); method will recognize the number value as a string value? (this might be a little unclear but the code should clear things up)
for (var i = 0; i < 3; i++) {
var useGetImageData = function(i){
var canvas=document.getElementById(i);
var context=canvas.getContext("2d");
var imageData = context.getImageData(0,0,canvas.width,canvas.height);
var data = imageData.data;
}
}
the canvas id's are; "0", "1", "2"
Try this. You also weren't calling the function (which is bad to create inside a loop anyhow).
var useGetImageData = function(i){
var canvas=document.getElementById(i);
var context=canvas.getContext("2d");
var imageData = context.getImageData(0,0,canvas.width,canvas.height);
var data = imageData.data;
}
for (var i = 0; i < 3; i++) {
// useGetImageData(''+i);
// As #Andrew points out, it gets interpreted as a string.
userGetImageData(i);
}
You don't have to do anything, getElementById already knows that element ids are always strings. The code you posted just works.
http://jsfiddle.net/FXS8u/

How to sort two arrays with the same random sort

Okay, I'm building a quiz application in jQuery/javascript.
The following little function is intended to randomize a series of possible answers for a question, as well as a series of photos. Each photo corresponds to one of the answers.
Before I call this function, the photos and answers are in the same order in each respective wrapped set.
The function does randomize both sets. But each one is randomized separately. I need them both to have the SAME randomization.
I can't figure out how to achieve this. I thought might be able to chain them jQuery style, but that's not right. I also tried separating out the function within the sort(), but that didn't do the trick either.
Can anyone help?
function randomize() {
var elemsPhotos = $('.photos').children('img').get();
var elemsQuests = $('.answers').children('.answerLine').get();
elemsPhotos.sort(function() { return (Math.round(Math.random())-0.5); });
elemsQuests.sort(function() { return (Math.round(Math.random())-0.5); });
$('.photos').remove('img');
$('.answers').remove('.answerLine');
for (var i=0; i < elemsQuests.length; i++) {
$('.photos').append(elemsPhotos[i]);
$('.answers').append(elemsQuests[i]);
}
}
If they comes in as pair, could you use a div to hold both of them and randomise the ordering of the divs instead?
otherwise, you can write a randomizer to generate a sequence . i.e. 1,4,2,3 as the indices, and then put the photos and answers in that order?
element 1->postion 1
element 2->postion 4
element 3->postion 2
element 4->postion 3
Why don't you just randomize an array with n values (where n is the number of questions/photos) and use that array to get the "random" index in each question/photo array?
var elemsPhotos = $('.photos').children('img').get();
var elemsQuests = $('.answers').children('.answerLine').get();
var n = elemsQuests.length;
var randomIndexes = [];
for (var i=0; i<n; i++) {
randomIndexes[i] = i;
}
randomIndexes.sort(function() { return (Math.round(Math.random())-0.5); });
$('.photos').remove('img');
$('.answers').remove('.answerLine');
for (var i=0; i < n; i++) {
$('.photos').append(elemsPhotos[randomIndexes[i]]);
$('.answers').append(elemsQuests[randomIndexes[i]]);
}
You can randomize pairs of (photo, quest):
var photos = $('.photos').children('img').get();
var quests = $('.answers').children('.answerLine').get();
var pairs = [];
for (var i=0; i < quests.length; i++)
pairs[i] = { photo: photos[i], quest: quests[i] };
// randomize 'pairs' any way you like
$.each(pairs, function(i, val) {
$('.photos').append(val.photo);
$('.answers').append(val.quest);
});

Categories