I'm trying to code a simple piece of javascript that reads in a CSV (pasted into a textarea on a webpage) and generates SQL insert statements but I keep getting undefined values when I reference the 2D array..
Please help!
var ret = "";
//alert("called");
//split the textarea into rows of text
var lines = text.split("\n");
//the first line of text is the table name
var table = lines[0];
//the second line of text is an array of the attribute names
var attrnames = lines[1].split(",");
var values = new Array();
//create a new array for each attribute
for (var i = 0; i < attrnames.length; i++) {
//the length of each array is the total number of rows
//of text - 2 (title row and attr row)
values.push(new Array(lines.length - 2));
}
//for each subsequent row, push the values to the appropriate arrays
for (var i = 2; i < lines.length; i++) {
//get the current row (value, value, value, value)
var thisrow = lines[i].split(",");
for (var j = 0; j < attrnames.length; j++) {
//add the j-th attribute (thisrow[j]) to its array (values[j])
values[j].push(thisrow[j]);
}
}
var insertIntoTable = "";
var tableName = "";
var attrList = "";
var valueList = "";
var lead = "";
//loop through each row
for (var k = 2; k < lines.length; k++) {
// --- ONE STATEMENT ---
//create the statements
insertIntoTable = "insert into table `";
tableName = table;
attrList = "` (";
valueList = "(";
for (var i = 0; i < attrnames.length; i++){
attrList += "`" + attrnames[i] + "`,";
}
//trim the last comma, then add the closing parenthesis.
attrList = attrList.substring(0, attrList.length-1) + ") ";
lead = insertIntoTable + tableName + attrList;
for (var i = 0; i < attrnames.length; i++) {
//this always points to undefined
valueList += "'" + values[i][k-2] + "', ";
}
lead += (" values " + valueList);
lead = lead.substring(0, lead.length-2) + ");\n";
ret += lead;
}
alert(ret);
In JavaScript you do not need to set the length of arrays. They are more like ArrayLists or something; read more at MDN's documentation.
When you do
var x = new Array(10); // array with "length" set to 10
x.push("somevalue");
then the value will be inserted at x[10] - at the end of the list. Log it in the console to see it yourself.
So either you drop the push() and use absolute indizes instead, or initialize the array as empty - best with the array literal syntax: []. The relevant area of your code should then look like this:
//create a new empty array for each attribute
for(var i = 0; i<attrnames.length; i++){
values.push([]);
}
You are making an array of length n, where n is the number of rows, and then you are pushing on n more elements of data. Start with 0 length arrays and you will be fine:
//create a new array for each attribute
for(var i = 0; i<attrnames.length; i++){
values.push(new Array(0)); // or '[]' -> the length of each array **will be** the total number of rows of text-2 (title row and attr row)
}
I would add caution that pasted data will be prone to lots of errors and potential security issues, such as SQL injection attacks. Aside from that, what happens if you have extra \ns at the end of your data? You will end up with more undefined data.
Related
Edit: Actually the logic is wrong here.
I solved it using Python3 with a dictionary that updates the last index at which a letter is seen. In dynamic programming lingo, it is similar to L.I.S (longest increasing subsequence).
If anyone knows how to solve this without using a dictionary, please comment because I learned DP in school and those lessons only used arrays so it should be possible with just arrays.
Original question:
I am trying Leetcode, 3. Longest Substring Without Repeating Characters.
I can solve this in Python making a 2D table for dynamic programming.
But in JavaScript which I am sort of new to, I am getting an error.
evalmachine.<anonymous>:41
var top = T[i-1][j]
^
TypeError: Cannot read property '1' of undefined
at lengthOfLongestSubstring (evalmachine.<anonymous>:4
My code:
/**
* #param {string} s
* #return {number}
*/
var lengthOfLongestSubstring = function(s) {
//empty string
if (s.length <= 0){
return 0
}
//initialize dict
var dict = {};
//initialize 2D table T
var T = new Array(s.length)
for (var i = 0; i<s.length; i++){
T[i] = new Array(s.length);
}
//base cases are diagonals
for (var i = 0; i < T.length; i++){
for (var j=0; j<T.length; j++){
if(i==j){
T[i][j] = 1;
}
else{
T[i][j] = 0;
}
}
}
//put base case in dict
//dict[s[0]]=1
for (var i=0; i < s.length; i++){
for (var j=i+1; j<s.length; j++){
var row_char = s.charAt(i);
var col_char = s.charAt(j);
if (row_char==col_char){
T[i][j] = 1;
}
else{
//console.log("j",j,T)
var left = T[i][j-1]
console.log(left)
var top = T[i-1][j]
console.log(top)
var bigger = Math.max(left,top);
T[i][j] = bigger + 1
}
}
}
//iterate each row to get max
var high = Number.MIN_SAFE_INTEGER;
for (var i = 0; i < s.length; i++){
if(T[i][s.length-1] > high){
high = T[i][s.length-1];
}
}
return high;
};
It is letting me fill the table with 0's and base case of 1 indexing like T[i][j] but then complaining about indexing like that to get the value which I don't understand.
I looked at this: How to get value at a specific index of array In JavaScript?
But it does not really say anything different.
On the first iteration of the loop following the //put base case in dict comment i is 0.
You're then attempting to access T[i-1][j], which is the equivalent of T[-1][j].
Because T doesn't have a -1 index, T[-1] resolves to undefined, upon which you attempt to access index [j] and you get the error you're seeing.
I have an array called countriesData that stores names for various countries, like this:
[Germany,France,Canada,Austria,Switzerland,Spain]
I'm trying to iterate over each element in that array, the idea is use each country in a query search over an external API, and then save the length of items in that external API. To put it simple, Im going through each country and counting how many items from that country are stored in an external database.
I have no problem accessing the database outside of the loop, however, I am unable to access it while inside the for iterator.This is my code:
for (var iter = 0; iter < countriesData.length; iter++) {
var obj = [];
var country = countriesData[iter]
var items;
var itemsCountry = 0;
$http.get("https://api.discogs.com/database/search?q={?country==" + country + " }&token=zwxZExVZTenjPTKumVeTDVRuniqhQLAxymdzSxUQ").then(function(response) {
items = response.data.pagination.items;
})
var str = "";
obj.push(countriesData[iter]);
obj.push(items);
for (var J = 0; J < myStats.data.length; J++) {
if (myStats.data[J].country == countriesData[iter]) {
itemsCountry++;
str += myStats.data[J].title + ", ";
}
}
obj.push(itemsCountry);
var str2 = str.substring(0, str.length - 2);
obj.push(str2);
newData.push(obj);
console.log("new obj : " + obj)
}
Basically, I need the var items to be updated acording to the length of the response data from http.get
This is an example of what I get once I console.log the obj:
France,,2,Thriller, D'eux
As you can see, the second element in the array is empty when it should have been an integer representing how many France related items where found in the database...
What is it that Im doing wrong? I get that the database is big and there might not be enough time for it to load. Any idead?
Thanks in advance :)
The problem is that your data call is asynchronous and hasn't completed before you try to push the data to the array.
function getCountryData(country) {
var obj = [];
var items;
var itemsCountry = 0;
$http.get("https://api.discogs.com/database/search?q={?country==" + country + " }&token=zwxZExVZTenjPTKumVeTDVRuniqhQLAxymdzSxUQ").then(function(response) {
items = response.data.pagination.items;
var str = "";
obj.push(country);
obj.push(items);
for (var J = 0; J < myStats.data.length; J++) {
if (myStats.data[J].country == countriesData[iter]) {
itemsCountry++;
str += myStats.data[J].title + ", ";
}
}
obj.push(itemsCountry);
var str2 = str.substring(0, str.length - 2);
obj.push(str2);
newData.push(obj);
console.log("new obj : " + obj)
})
}
for (var iter = 0; iter < countriesData.length; iter++) {
var country = countriesData[iter];
getCountryData(country);
}
I want this code to display information from a text input from a form on an HTML page, using the array, it would take the information into an array, then display it back on a textarea, though each time it overrides the first line, not displaying right
var count = 0;
var input = document.forms["ShoppingForm"]["choiceTxt"].value;
function listChoice(){
count++;
var arr = new Array();
arr[count] = document.forms["ShoppingForm"]["choiceTxt"].value + "\n";
for(var i = 0; i <= arr.length; i++){
document.forms["ShoppingForm"]["listDisplay"].value = count + ". " +
arr[i] + "\n";
}
}
The issue seems to be with this line var arr = new Array();. Everytime it will create a new array.
Try my declaring the array outside the function.Also the seems to be no need of the count. The value can be simply pushed in the array
var count = 0;
var arr = [];
var input = document.forms["ShoppingForm"]["choiceTxt"].value;
function listChoice(){
arr.push(document.forms["ShoppingForm"]["choiceTxt"].value + "\n");
for(var i = 0; i <= arr.length; i++){
document.forms["ShoppingForm"]["listDisplay"].value = count + ". " +
arr[i] + "\n";
}
}
I am building a web app which contains a DOM table. This is my code that should create a table from an array:
function create_table() {
var tablediv=document.getElementById('icon-table');
var table = document.createElement("table");
var grid = [[15][15]];
var template = "pixel-{1}-{2}";
table.className = "icon-table";
tablediv.appendChild(table);
for (var i = 0; i < 16; i++) {
var tr = document.createElement("tr");
table.appendChild(tr);
for (var j = 0; j < 16; j++) {
var td = document.createElement("td");
td.className = "icon-pixel";
td.id="pixel-"+ i + "-" + j;
td.style.backgroundColor = "rgb(255,255,255)"; // no dash - css attribute name becomes camelCase
grid[i][j] = td;
td.addEventListener("click", setpixel)
td.addEventListener("mousedown", pinselpixel)
tr.appendChild(td);
}
}
}
The assignment grid[i][j] = td; fails during the first loop iteration.
On the console in my browser the output says:
TypeError: undefined is not an object (evaluating 'grid[i][j] = td')
what am I missing?
There's a couple of problems here. First, you seem to be under the impression that
[[15],[15]]
will create an an array with two sub-arrays, each with 15 keys.
Instead, what that actually gives you is an array with two sub-arrays each containing one key each, with the value 15.
You probably meant this:
[new Array(15), new Array(15)]
Passing an integer to the array constructor creates the slots; passing it to an array literal simply adds that value to the array.
Even then, this approach isn't ideal. Yes, you're containing 15 (actually you presumably meant 16) slots, but they're just undefined slots right now, so this line will fail, since you can't treat undefined as an array:
grid[i][j] = td; //grid[i] == undefined, not an array
Better this (truncated for brevity):
for (var i = 0; i < 16; i++) {
grid[i] = []; //<-- create the row array in the loop
var tr = document.createElement("tr");
table.appendChild(tr);
for (var j = 0; j < 16; j++) {
var td = document.createElement("td");
grid[i][j] = td; //<-- now we can append the column cell
tr.appendChild(td);
}
}
you are trying to loop over an array of array which has 2 elements inside. Each element is (like i said) an array, with a single entry - in your case 15.
Afterwards you are trying to iterate from 0 up to 15.
So your iterations should at first loop over grid array and afterwards over grid's elements up to their length.
but in my opinion it is not necessary to loop over an array here. just do the following:
var myGrid = []
for (var i = 0; i < 16; i++) {
for var k = 0; k < 16; k++) {
//do your stuff
myGrid[i][k] = td
}
}
this should work
The method of intializing the two dimensional array is wrong.
Please use the below method to initialize.
var grid = new Array(15);
for (var i = 0; i < 16; i++) {
grid[i] = new Array(15);
}
First we create the rows of the array (15 rows), then using a for loop we initialize 15 columns for each row. Then the code works fine!
function create_table() {
var tablediv=document.getElementById('icon-table');
var table = document.createElement("table");
var grid = new Array(15);
for (var i = 0; i < 16; i++) {
grid[i] = new Array(15);
}
var template = "pixel-{1}-{2}";
table.className = "icon-table";
tablediv.appendChild(table);
for (var i = 0; i < 16; i++) {
var tr = document.createElement("tr");
table.appendChild(tr);
for (var j = 0; j < 16; j++) {
var td = document.createElement("td");
td.className = "icon-pixel";
td.id="pixel-"+ i + "-" + j;
td.style.backgroundColor = "rgb(255,255,255)"; // no dash - css attribute name becomes camelCase
grid[i][j] = td;
td.addEventListener("click", function(){console.log("clicked");})
td.addEventListener("mousedown", function(){console.log("mousedown");})
tr.appendChild(td);
}
}
}
create_table();
<div id="icon-table"></div>
Your grid initialization is wrong. As mentioned by some comments:
var grid = [[15][15]];
is equivalent to:
const arr = [15]; // array with one element, 15
var grid = arr[15]; // 16th element, which doesn't exist
You probably instead want:
var grid = new Array(15).fill(new Array(15));
Which will give you a two-dimensional array that is 15 "wide" and 15 "tall".
That said, you really don't need to prefill your grid unless it is a requirement for some other reason (like you are printing out a chessboard or something that always has a fixed size).
Can change to this and try it?
var grid = [[15][15]];
to
var grid = [new Array(15), new Array(15)];
I want to display duplicates found from the sheet in a Browser.Msg box and send the duplicate strings via email.
Additionally extra column could be written to that row where status "DUPLICATE - YES" would be written. However just to get it via email / in a popup would be enough.
I have tried logging the data. I have tried setting variables.
function checkDuplicates() {
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("DATA!F2:F"); // Set Any Range
// "A:A" is for Column A
// And if you want to check duplicates for whole sheet then try this:
// var dataRange = sheet.getDataRange();
var data = dataRange.getValues();
var numRows = data.length;
var numColumns = data[0].length;
var dupes = false;
var okdupes0 = 0;
var nodupes0 = 0;
var totbookings0 = 0;
var formats = [];
var values = [];
for (var i = 0; i < numRows; i++) {
formats[i] = [];
for (var j = 0; j < numColumns; j++) {
formats[i][j] = 'WHITE';
if (data[i][j] != '') {
values.push([data[i][j], i, j]);
}
}
}
var numValues = values.length;
for (var k = 0 ; k < numValues - 1; k++) {
if (formats[values[k][1]][values[k][2]] == 'WHITE') {
for (var l = k + 1; l < numValues; l++) {
if (values[k][0] == values[l][0]) {
formats[values[k][1]][values[k][2]] = 'RED';
formats[values[l][1]][values[l][2]] = 'RED';
var dupes = true;
}
}
var okdupes = okdupes0++;
}
var totbookings = totbookings0++;
}
if (dupes) {
// var okdupes = okdupes -1;
var nodupes = totbookings - okdupes;
var emailAddress = "myemail#gmail.com"; // First column
var message = + nodupes + " Duplicate voucher(s) has been found from the system. Duplicate vouchers has been marked with red color."; // Second column
var subject = "System: " + nodupes + " Duplicate Voucher(s) Found!";
MailApp.sendEmail(emailAddress, subject, message);
Browser.msgBox('Warning!', ''+ nodupes +' Possible duplicate voucher(s) has been found and colored red! Please contact the rep who has made the sale. '+ totbookings +' bookings has been scanned through for duplicates.', Browser.Buttons.OK);
} else {
Browser.msgBox('All good!', 'No duplicate vouchers found.', Browser.Buttons.OK);
}
dataRange.setBackgroundColors(formats);
}
You could convert the array of values to a string, then use match to count occurrences.
This code works to find duplicates, even from a two dimensional array. It doesn't determine what cell the duplicate came from. The values of all the duplicates are put into an array.
function findDups() {
var testArray = [['one','two','three'],['three','four','five']];
var allDataAsString = testArray.toString();
Logger.log('allDataAsString: ' + allDataAsString);
//Create one Dimensional array of all values
var allDataInArray = allDataAsString.split(",");
var pattern;
var arrayOfDups = [];
for (var i = 0;i<allDataInArray.length;i++) {
var tempStr = allDataInArray[i];
// the g in the regular expression says to search the whole string
// rather than just find the first occurrence
var regExp = new RegExp(tempStr, "g");
var count = (allDataAsString.match(regExp) || []).length;
Logger.log('count matches: ' + count);
if (count > 1 && arrayOfDups.indexOf(tempStr) === -1) {
arrayOfDups.push(tempStr);
};
};
Logger.log('arrayOfDups: ' + arrayOfDups);
Browser.msgBox('Thest are the duplicate values: ' + arrayOfDups);
//To Do - Send Email
};
The above example code has a hard coded two dimensional array for testing purposes. There are two occurrences of an element with the value of 'three'.