I have an if statement that loops through csv data. There are 51 rows that I have parsed in by new lines and by commas to give me individual arrays for each row. My issue is my if statement doesn't seem to be working and honestly I just don't see why. Raw is the csv file.
Updated heres how i split the csv file
console.log("Loaded: " + data.length);
console.log("feature layer graphics: " + fl.graphics.length);
console.log(data);
var raw = data.split("\n");
var valMin = Infinity;
var valMax = -Infinity;
var arrayForBreaks = [];
console logs returns 51 false
then there is one console log of true
for (var i = 0; i < raw.length; i++) {
var row = raw[i].split(",");
var name = " ";
var amount = " ";
if (row.length >= 6) {
name = row[0];
amount = row[1];
}
console.log(isNaN(row[1]));
stateData[name] = row;
valMin = Math.min(valMin, row[1]);
valMax = Math.max(valMax, row[1]);
arrayForBreaks.push(parseFloat(amount));
}; //end for loop
So my question is in the if statement I'm checking to see if the length of the first element in the array is greater that 6 if it is dump that name and amount in those variables. I also had a else statement to fill in the last array. But it seems to keep adding one empty line to the end of the data.
So my question is in the if statement I'm checking to see if the length of the first element in the array is greater that
Negative.
You are checking to see if there are more than 6 elements in the array, or 6 comma delimited items.
To check the length of the first element you would need to:
if (row[0].length >= 6) {
....
[…] in the if statment I'm checking to see if the lengh of the first element in the array is greater tha[n] 6
No, that’s not what you are doing. row.length will return the number of elements of row – and row is an array you got from splitting the raw string by commas. If you want to check the length of the first element, you should check row[0].length instead.
Related
I am trying to display an array in HTML so that the displayed integers are broken into a new line. The JS is breaking them into a new line, yes, but when the numbers are single number like from 0 - 9, they don't break into a new line. The numbers that break into a new line only start from double digit ie. 10 going upwards.
Here is my JS code: I think there is something wrong with the FOR LOOP in the function displayArray, but I just cant figure it out. This is one of the final pieces to almost tie this up!
Thanking you in advance for any contributions!
//Array to hold statistics of number of pages read per sitting over a period of time
const myArray = [];
//Function to calculate number of pages read
let calculate = () => {
var start = document.getElementById("number1").value;
var end = document.getElementById("number2").value;
document.getElementById("number1").value = ""; // make START empty
document.getElementById("number2").value = ""; //make END empty
let totalNumber = end - start;
myArray.push(totalNumber); //Push total number into array
document.getElementById("congrats").textContent =
"Congrats, you read " + totalNumber + " pages today!";//display message
document.getElementById("rightpane").textContent = myArray;//push array into HTML
displayArray();//Call display array
};
//Function to display myARRAY broken down to a new line
const displayArray = ()=> {
let displayedNumbers='';
for (i = 0; i < myArray.length; i++){
displayedNumbers += myArray[i] + "\n";
};
document.getElementById("rightpane").textContent = displayedNumbers;//Append myArray into HTML
}
Append a prefixed 0 to any number less than 10
You could append a number to the start of the list item and increase it by one each time.
I'm not really sure what you are trying to do, but if you want numbers to appear in new line without using lists and CSS you can wrap them in 'pre' tags and it should break it to new row like this:
displayArray();
function displayArray(){
myArray = [0,1,2,3,4];
let displayedNumbers='';
for (i = 0; i < myArray.length; i++){
displayedNumbers += "<pre>"+myArray[i] + "</pre>";
};
document.getElementById("rightpane").innerHTML = displayedNumbers;//Append myArray into HTML
}
#rightpane{
background : #000;
height : 200px;
width: 100px;
color:white;
padding: 5px;
}
<pre>0</pre><pre>1</pre><pre>2</pre><pre>3</pre>
<div id="rightpane"></div>
I have just made your code some corrections...
and adding parseInt
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
and you also have to look at white-space: pre
https://developer.mozilla.org/en-US/docs/Web/CSS/white-space
// Array to hold statistics of number of pages read per sitting over a period of time
const myArray = []
, Num_1 = document.getElementById('number1')
, Num_2 = document.getElementById('number2')
, congrats = document.getElementById("congrats")
, rightpane = document.getElementById("rightpane")
const LeadZeros =(val,lg)=>('0'.repeat(lg)+val).slice(-lg)
// Function to calculate number of pages read
const calculate =_=>
{
let totalNumber = parseInt(Num_2.value) - parseInt(Num_1.value)
Num_1.value = '' // make START empty
Num_2.value = '' // make END empty
myArray.push( LeadZeros(totalNumber,3) ) // Push total number into array
/*
// or:
myArray.push( totalNumber.toString(10).padStart(3, '0') )
*/
congrats.textContent = `Congrats, you read ${totalNumber} pages today!` // display message
rightpane.textContent = myArray.join("\n") // push array into HTML
}
I also remove your function DisplayArray() and use Array.join() method .
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join
leadZero function use :
https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/String/repeat
https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/String/slice
leadZero is divided into two parts: (for example lg = 3)
1) '0'.repeat (3) + val ===' 000 '+ val
if val = 5 it gives '0005'
if val = 42 this gives '00042'
nota: the first value is a string and force the setting in value string too
2) () .slice (-lg) <=> () .slice (-3)
when we put a negative value the method string.slice pars the last character and goes up (from 3 here)
the last 3 characters of:
'0005'.slice(-3) => '005'
'00042'.slice(-3) => '042'
Try as I might I CANNOT decipher the problem that I'm having writing new rows to a sheet. I've done this several times and I've debugged this thoroughly using Logger.log, but I just can't solve it. Here's a summary of what I'm doing, a code snippet, and a log:
What I'm doing:
Adding rows to a sheet (below existing rows)
73 new rows are stored stored in array: Grade Rows
When attempt to write the new rows to the sheet, get this error:
Incorrect range width, was 1 should be 26
Here’s the code including some Logger.logs:
var BeginningRow = LastSGRowSheet + 1;
var EndingRow = BeginningRow + SGPushKtr -1;
Logger.log("BeginningRow =>" + BeginningRow + "<=, SGPushKtr =>" + SGPushKtr + "<=, Ending Row =>" + EndingRow + "<=");
var GradesRangeString = 'A' + BeginningRow + ':' + LastStudentGradesColumnLetter + EndingRow;
Logger.log("GradesRangeString =>" + GradesRangeString + "<=");
StudentGradeSheet.getRange(GradesRangeString).setValues(GradeRows);
The error occurs in that last line of code.
Here’s the log:
17-12-31 11:51:15:763 EST] BeginningRow =>364<=, SGPushKtr =>73<=, Ending Row =>436<=
[17-12-31 11:51:15:764 EST] GradesRangeString =>A364:Z436<=
Let's say that your data array is dA then the number of rows in that array is dA.length and assuming its a rectangular array then the number of columns is vA[0].length. So your output command has to be some thing like this.
sheet.getRange(firstRow,firstColumn,dA.length,dA[0].length).setValues(dA);
If you'd like to learn a little more about this problem check this out.
You could also append each row to the current sheet one row at a time in loop.
It's hard to know why GradeRows doesn't match your range without seeing all of your code.
Using Cooper's getRange arguments will likely reveal your problem, and will prevent you from having to update your row and column variables when you make changes to your code. Another issue that gets me sometimes is the fact that the setValues array needs to be exactly the same dimensions as the range. If one row has a different length, it will fail. If the logic I use to create row arrays can result in different lengths, I use the function below to make sure my arrays are symmetric before writing them to a sheet. It is also helpful for debugging.
/**
* Takes a 2D array with element arrays with differing lengths
* and adds empty string elements as necessary to return
* a 2D array with all element arrays of equal length.
* #param {array} ar
* #return {array}
*/
function symmetric2DArray(ar){
var maxLength;
var symetric = true;
if (!Array.isArray(ar)) return [['not an array']];
ar.forEach( function(row){
if (!Array.isArray(row)) return [['not a 2D array']];
if (maxLength && maxLength !== row.length) {
symetric = false;
maxLength = (maxLength > row.length) ? maxLength : row.length;
} else { maxLength = row.length }
});
if (!symetric) {
ar.map(function(row){
while (row.length < maxLength){
row.push('');
}
return row;
});
}
return ar
}
How about using appendRow()? That way you don't need to do lots of calculations about the range. You can loop through your data and add it row by row. Something like this:
myDataArr = [[1,2],[3,4],[5,6]]
myDataArr.forEach(function(arrayItem){
sheet.appendRow([arrayItem[0],arrayItem[1]])
})
// This will output to the sheet in three rows.
// [1][2]
// [3][4]
// [5][6]
I am trying to write the most basic of functions and struggling The purpose of the script is to take 2 inputs (ranges) and then use those cells to construct a single, long string of the contents of all the cells concatenated....it doesn't work (see code below).
It has something to do with a range not really being an array because when I hardcoded the array it worked fine. If I have this layout:
Header1 Header2
Comment1 Comment2
Comment1a Comment2a
Note that each string is in its own cell in the spreadsheet. What I want is to get:
Header1
Comment1
Comment1a
Header2
Comment2
Comment2a
BUT all of this should be in a single cell.
Instead, what happens is:
Header1, Header2
Comment1, Comment1a, Comment2, Comment2a
all in a single cell.
Here is my current code....totally confused and no documentation anywhere intelligible doesn't help.
function concatComments(headerRange,commentRange)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var out=''
newline = String.fromCharCode(10)
hVals = headerRange.split()
cVals = commentRange.split()
return hVals
// Test whether input is an array.
if (headerRange.map && commentRange.map)
{
/* process array or range */
// headerRange = ['Header1','Header2']
// commentRange = ['comment1','comment2', 'comment2a']
// var hValues = ss.getRange(headerRange).getValues()
// var cValues = ss.getRange(commentRange).getValues()
for( i=0; i< commentRange.length; i++)
{
if(commentRange[i].length >= 0)
{
out += headerRange[i] + newline + " " + commentRange[i] + newline
}
}
}
else
{
/*process single value */
out = headerRange[0] + newline + " " + commentRange[0]
}
return out
}
If anyone could explain what is going on I would greatly appreciate it.
Thanks in advance.
paul
You can also do this without Apps Script with the JOIN Sheets function, e.g.
=JOIN(" ", A1:A3)
Will concatenate the values in A1:A3 separated by a space.
For your example, you'd need something more complicated like
=JOIN(CHAR(10),A1, ARRAYFORMULA(" " & A2:A3), B1, ARRAYFORMULA(" " & B2:B3))
[Example spreadsheet]
Extracting Arrays from Google Sheets with Google Apps Scripts using the:
getRange().getValues() methods
Header1 Header2 .getValues() for headers
Comment1 Comment2 | .getValues() for comments
Comment1a Comment2a | ^^^^^^^^^^^^^^^^^^^^^^
Use the following test arrays as this is what will be returned by getValues():
[["Header1","Header2"]]
[["Comment1", "Comment2"],["Comment1a", "Comment2a"]]
so, being that array indices are zero based:
headers[0][1] == "Header2"
comments[1][0] == "Comment1a"
comments[1] == ["Comment1a", "Comment2a"]
Empty cells are represented by ""
Comment1 Comment2
Comment2a
Would be represented as:
[["Comment1", "Comment2"],["", "Comment2a"]]
each row is an array within the larger array and every row array will contain the same number of elements even when some cells are empty.
To find out the number of:
Rows comments.lengthreturns the number of row arrays
Columns comments[0].lengthreturns the number of elements(columns) in the first row array and being that all row arrays contain the same number of elements only one need be used to derive the number of columns.
See if this works:(arguments are returned as value arrays therefore .getValues() is not used)
function concatComments(headerRange,commentRange) {
var out=''
var newline = String.fromCharCode(10);
for(var c = 0; c < headerRange[0].length; c++) {
if( c > 0 ) out = out + newline;
out = out + headerRange[0][c] + newline;
for(var r = 0; r < commentRange.length; r++) {
if(commentRange[r][c] != "") {
out = out + " " + commentRange[r][c] + newline;
}
}
}
return out;
}
i am relatively new to stackoverflow and have searched for some time for an answer to my question. I found some links like this one How to split a comma-separated string?
but still can't quite understand what I am doing wrong with my short little javascript program.
Anyway here it is. Help would be appreciated.
I basically am trying to create a prompt that asks the user to input 3 numbers seperated by commas, then change that string into an array so that I can multiply the values later on. So far, when i try to console.log this my results are as follows : 1,2
It doesn't print out the third digit(3rd number entered by the user).
var entry = prompt("Triangle side lengths in cm (number,number,number):")
if(entry!=null && entry!="") {
entryArray = entry.split(",");
for (i=0; i<3; i++)
{
entryArray[i] = entry.charAt([i]);
}
}
console.log(entryArray[0] + entryArray[1] + entryArray[2]);
Split creates an array already. So, if you enter 1,2,3, you get an array like this when you split it: ["1", "2", "3"]. In your for loop, you are getting the characters from the original input, not your array. In order to add them, you need to change the input to numbers since they are considered strings. So your for loop should look like this:
for (i=0; i<3; i++)
{
entryArray[i] = parseFloat(entryArray[i]);
}
overwriting the strings with the digits.
Try
for (i=0; i<3; i++)
{
entryArray.push(parseInt(entryArray[i]);
}
You can remove the body of the for。like this:
var entry = prompt("Triangle side lengths in cm (number,number,number):")
console.log(entry);
if(entry!=null && entry!="") {
entryArray = entry.split(",");
console.log(entryArray);
}
console.log(entryArray[0] + entryArray[1] + entryArray[2]);
try this code, i removed your looping which was overwriting the array.
var entry = prompt("Triangle side lengths in cm (number,number,number):");
if(entry!=null && entry!="") {
entryArray = entry.split(",");
console.log(entryArray[0] + entryArray[1] + entryArray[2]);
}
This should be a quickie, but I'm scratching my head as to why this bit of JavaScript isn't working for me. The goal is to take the value of an input box (string of words separated by spaces), list these words as items in an array, and remove those which are fewer than 3 characters:
var typed = $('input').val();
var query = typed.split(" ");
var i=0;
for (i=0; i<query.length; i++) {
if (query[i].length < 3) {
query.splice(i,1);
}
}
Have this running onkeyup for the input box and it seems to work, but only about 50% of the time (strings of 1 and 2 characters somehow find their way into the array on occasion). Any suggestions would be hugely appreciated.
The problem is that you are iterating while removing the elements. Consider this array:
["he", "l", "lo world"]
Initially your loop starts at index 0 and removes "he" from the array. Now the new array is
["l", "lo world"]
In the next iteration i will be 1, and you will check "lo world"'s length, thus ignoring the "l" string altogether.
Use the filter method in Array to remove the unwanted elements.
var biggerWords = query.filter(function(word) {
return word.length >= 3;
});
Besides the iterating problem, you may also see unexpected entries if you type multiple spaces
try
var query = typed.split(/\s+/);
This way it will split on any number of spaces, instead of each individual one
The problem is that you're slicing the array while counting forward. Think about it...if you take an index point out of the array, thereby shortening it by one, incrementing i and moving on to the next one actually moves one further than you want, completely missing the next index. Increment i--, start at query.length-1, and make the condition that i>=0. For an example of this in action, check it out here:
http://jsfiddle.net/kcwjs/
CSS:
input {
width:300px;
}
HTML:
<input id="textbox" type="text" />
<div id="message"></div>
Javascript:
$(document).ready(function() {
$('#textbox').keyup(checkStrings);
});
function checkStrings(e) {
var typed = $('#textbox').val();
if (typed == "") return false;
var query = typed.split(" ");
var querylen = query.length;
var acceptedWords = '';
var badWords = '';
for (var i = querylen-1; i >= 0; i--) {
if (query[i].length < 3) {
badWords += query[i] + " ";
} else {
acceptedWords += query.splice(i,1) + " ";
}
}
$('#message').html("<div>Bad words are: " + badWords + "</div>" +
"<div>Good words are: " + acceptedWords + "</div>");
}
Try this code, it get's rid of any 3 character words, as well as making sure no empty array elements are created.
typed.replace(/(\b)\w{1,3}\b/g,"$1");
var query = typed.split(/\s+/);
hey i think you should use a new array for the result. since you are removing the element in array. the length is changed. here is my solution
var typed = "dacda cdac cd k foorar";
var query = typed.split(" ");
var i=0;
var result = [];
for (i=0; i<query.length; i++) {
if (query[i].length >= 3) {
result.push(query[i]);
}
}