Getting read property error undefined in node.js - javascript

I am working on scraping part and i am getting the data well, but when I am iterating the array and trying to get the data throwing me
TypeError: Cannot read property '3' of undefined
My code is:
$('table#blob1 tr.insRow').filter(function(){
var data = $(this);
i = i + 1;
bow_arr[i] = new Array(6);
bow_arr[i][1] = data.children(1).text();
bow_arr[i][2] = data.children(2).text();
bow_arr[i][3] = data.children(3).text();
bow_arr[i][4] = data.children(4).text();
bow_arr[i][5] = data.children(5).text();
bow_arr[i][6] = data.children(6).text();
})
Here i am creating two dimensional array and inserting the data into it. and i am able to get all the children values correctly and i have inserted all those data into the two dimensional array.
The filter function runs for 5 times since it is encountered five times.
for(i=0;i<1;i++){
console.log(bow_arr[i][3]+" - "+bow_arr[i][4]);
}
The above code i am just trying to print the values but i am getting TypeError like this.
TypeError: Cannot read property '3' of undefined

According your code, your iterator loop is written in a wrong way.
In your code you have
i = i + 1;
Which makes your array look like this :
bow_arr[0] === undefined; // equals true
bow_arr[1] === [ 'text from child 1', 'text from child 2' ... ]
bow_arr[2] === [ 'text from child 1', 'text from child 2' ... ]
And your iterator
for(i=0;i<1;i++) { ... }
Will iterate only 0 one time.
You have two possibilities. To fix your code or to fix your iterator
I choose to fix your iterator, which should look like :
for(i=1;i<bow_arr.length;i++){
console.log(bow_arr[i][3]+" - "+bow_arr[i][4]);
}
Just to make sure you can also include a check to see if this item in the array is undefined.
for(i=1;i<bow_arr.length;i++) {
if ( !bow_arr[i] || !bow_arr[i][3] || !bow_arr[i][4] ) continue;
console.log(bow_arr[i][3]+" - "+bow_arr[i][4]);
}

As VisioN says you are indexing 0 but you have not entered anything into that post. Initiate i as 0 and you should be fine :). Move incrementation to end of filter function.
var i = 0;
$('table#blob1 tr.insRow').filter(function(){
var data = $(this);
bow_arr[i] = new Array(6);
bow_arr[i][1] = data.children(1).text();
bow_arr[i][2] = data.children(2).text();
bow_arr[i][3] = data.children(3).text();
bow_arr[i][4] = data.children(4).text();
bow_arr[i][5] = data.children(5).text();
bow_arr[i][6] = data.children(6).text();
i = i + 1;
})
Fyi: You loop ONCE in the code below = What's the point of having a loop? :)
for(i=0;i<1;i++){
console.log(bow_arr[i][3]+" - "+bow_arr[i][4]);
}

Related

for loop in an array

I ran into a rather weird problem when I try to code a specific part of my bot! To make it simple and short , I have an object array that contains various properties ( see code for examples). What i want to do is I want to get all the specific property in that array ( name for example ) and print that out in a console. I tried looping using a simple for loop , and every successful loop, i asked the console to log arrayname[i].name! See code for clarification!
module.exports = {
commands: ["test"],
callback: (message, arguments, text) => {
const data = [
{ name: "Ren", id: "NURE1" },
{ name: "Isa", id: "SCIS1" }
]
for (var i = 0; i <= data.length; i++) {
console.log(data[i].name)
}
}
}
the problem is it does log the code as expected - Ren and Isa in this case for example but as soon as the console log, the app crashes throwing the error - property name is undefined ;-; - the same goes when i used id. Is there something I am doing wrong??
This is because data only has 2 items (index 0 and index 1), but you're trying to access 3 items (index 0, 1, and 2). Index 2 is undefined, so it's throwing an undefined error. You should use i < data.length instead of i <= data.length in your for loop.
You can also use a for ... of loop to avoid issues like this with indices:
for (let item of data) {
console.log(item.name);
}

Generating a new array if a certain criteria is met (Javascript)

I have an array of users who all need to be added to a group array. If the the group array has less than 3 users, i want to add the user to that group array. If the group array already has 3 user, I want to push the current group array to another array that collects all the groups and start another new group array for the next 3 users until there are no users.
Error -
let group[i] = [];
Unexpected token [
I have been racking my brains trying to figure this out. Maybe staring at the screen for too long.
This is what i have been trying with different variations but the console is not impressed -
function createGroups(totalPeople){
let i = 1
let group[i] = [];
let array = totalPeople
totalPeople.map((user) => {
if(group[i] =< 3){
group[i].push(user)
}else{
array.push(group[i]);
i++
}
})
};
totalPeople is an array created earlier in my code and this is the only part of the file that is not running as intended. Any help with a method on how to do this or suggestions on fixing this code would be of great help! thank you!
Try to initialize group as an array:
let i = 1
let group = [] // Initialize as an array
group[i] = [];
let array = totalPeople
totalPeople.map((user) => {
if(group[i] =< 3){
group[i].push(user)
}else{
array.push(group[i]);
i++
}
})
There are a few issues in your code :
function createGroups(totalPeople){
let i = 1
let group[i] = []; // issue #1
let array = totalPeople
totalPeople.map((user) => {
if(group[i] =< 3){ // issues #2 and #3
group[i].push(user)
}else{
array.push(group[i]); // issue #4
i++; // issue #5
}
})
};
Issue #1 :
You need to define group as an array before adding an index.
let group = [];
group[i] = [];
Issue #2 :
Looks like you meant to compare group[i].length and 3
Issue #3 :
Use <= instead of =< to compare your numbers. Also, if you compare the length with <= 3, you'll have 4 people per group. Because the first index in arrays is 0.
Issue #4 :
You are pushing to array, which is a reference to totalPeople. Is this what you meant? Because I doubt it will produce the expected results. You may want to initialize an empty array and push your group[i] array in it. And then, return that new array. It's usually a good practice in functionnal programming to return a new array and not modify the one passed as a parameter.
Issue #5 :
If you increment i, you need to initialize group[i] as an array, otherwise you won't be able to push in it when comes the next loop iteration.
Differnet logic :
Now that you fixed the issues in your code, here's a Snippet showing another way to do it using Array.prototype.reduce :
const totalPeople = ["Joe", "Jack", "Jerry", "Jane", "Mary", "Billy", "Vicky", "Bobby"];
const groupsOfThree = totalPeople.reduce((accumulator, currentPerson, index) => {
// pushing the current person in the topest group in the accumulator
accumulator[accumulator.length-1].push(currentPerson);
// if it's the 3rd person, we're pushing the an empty group in the accumulator
if (index % 3 === 2) {
accumulator.push([]);
}
return accumulator;
}, [[]]); // the initial value of the accumulator will be an array containing an empty group
console.log(groupsOfThree);

How would I go about using a multidimensional array variable in javascript

Hi there before I start I did try looking through the search about writing variables so if this has been asked and answered then I do apologise but this is baffling me ....
So here goes ..
example of what I am talking about
var i = e[ab]
var n = e[cd][ef]
var t = e[cd][gh]
I know that when I want var i I can put e.ab but how would I go about writing var n and var t
So assuming your object looks like this (based on your description, it sounds like you want to access an object which is the property of another object), and you want to access them through the indexer properties (which would be a property of a property).
var e = {
ab : "variableOne",
cd : {ef:"ef object"},
gh : {ij:"ij object"},
}
var i = e["ab"]
//if these are properties, then you need to add quotes around them
//to access a property through the indexer, you need a string.
var n = e["cd"]["ef"]
var t = e["gh"]["ij"]
console.log(i);
console.log(n);
console.log(t);
console.log("this does the same thing:")
console.log(e.ab);
console.log(e.cd.ef);
console.log(e.gh.if);
In your example the object would look like
//e is the parameter, but I show it as a variable to show
// it's relation to the object in this example.
e = {
now_playing: {artist:"Bob Seger"; track:"Turn the Page"}}
}
this is different than an array of arrays:
var arr = [
['foo','charlie'],
['yip', 'steve'],
['what', 'bob', 'jane'],
];
console.log(arr[0][0]); //foo
console.log(arr[0][1]); //charlie
console.log(arr[1][0]); //yip
console.log(arr[1][1]); //steve
console.log(arr[2][2]); //jane
https://jsfiddle.net/joo9wfxt/2/
EDIT:
Based on the JSON provided, it looks like parameter e in the function is assigned the value of the item in the array. With your code:
this line will display: "Rock you like a hurricane - Nontas Tzivenis"
$(".song_title .current_show span").html(e.title);
and this line will display: "Rascal Flatts - Life is a Highway".
$(".song_title .current_song span").html(e.np);
If it's not displaying you might want to double check your JQuery selectors. This ".song_title .current_song span" is selecting it by the classes on the element.
I think you are in need of a bit of a refresher on basic JavaScript syntax. Here's how you can assign an "empty object" to a variable, then start to assign values to it's properties:
e = {}
e.ab = {}
e.cd = {}
e.cd.ef = "data"
or you can use the associative array syntax for property access:
e = {}
e["ab"] = {}
e["cd"] = {}
e["cd"]["ef"] = "data"
You see the latter is using the object e like a two-deep associative array. Is that what you are looking to do?
JavaScript is not strongly typed. So an Array "a" could contain objects of different types inside.
var a = [ "a value", [1, 2, 3], function(){ return 5 + 2;}];
var result = a[0]; //get the first item in my array: "a value"
var resultOfIndexedProperty = a[1][0]; //Get the first item of the second item: 1
var resultOfFunc = a[2](); //store the result of the function that is the third item of my array: 7
Hope this helps a little.

unusual behavior with object creation in Javascript

I am not getting expected values through this code, please help me to identify the bug in this code. I am newbie to java script, I doubt the problem might be due to object creation or object scope. I debugged it in several ways but unable to identify the problem.
Also please tell me if the data I am creating is in JSON format or not. If not what is the equivalent JSON format ?
PS.id = -1;
PS.data = {
formData:[]
};
PS.setDef = [];
PS.item = {};
if(cond){
PS.item.Name = "From";
PS.item.Type = "STRING";
PS.setDef.push(PS.item);
alert(PS.setDef[0].Name);
PS.item.Name = "To";
PS.item.Type = "STRING";
PS.setDef.push(PS.item);
alert(PS.setDef[1].Name);
}//here alerts are coming properly. getting 'from' and 'to' in alerts
PS.data.formData.push({"id":id++, "setDef":[PS.setDef[0]]});
PS.data.formData.push({"id":id++, "setDef":[PS.setDef[1]]});
//expected id 0
alert(PS.data.formData[0].id);
//expected name 'from'
alert(PS.data.formData[1].setDef[0].Name);
//expected id 1
alert(PS.data.formData[1].id);
//expected name 'to'
alert(PS.data.formData[1].setDef[1].Name);
Instead of getting 0 and 1 as ID's and names as 'from' and 'to' I am getting following values
-1
0
to
to
Update 1 : here PS means page scope which is already declared, edited the alerts to print variables.
Your code had a couple of logical errors and a typo. This is the corrected version (changes have been marked in comments with **HERE**)
PS.id = -1;
PS.data = {
formData:[]
};
PS.setDef = [];
if(cond){
// *** HERE ***
// Your code was creating just one object instance in
// PS.item, pushing it, mutating and pushing it again
// The "alert" call was apparently correct just because
// it was done before mutating the object. Just moving
// both alerts at the end would have shown the problem.
PS.setDef.push({Name: "From", Type: "STRING"});
alert(PS.setDef[0].Name);
PS.setDef.push({Name: "To", Type: "STRING"});
alert(PS.setDef[1].Name);
}
// **HERE**
// id++ increments a value but returns the value BEFORE the increment.
// Thus formData[0] is expected to have .id == -1, not 0.
// If you want the value AFTER the increment then use ++id.
PS.data.formData.push({"id":++id, "setDef":[PS.setDef[0]]});
PS.data.formData.push({"id":++id, "setDef":[PS.setDef[1]]});
//expected id 0
alert(PS.data.formData[0].id);
//expected name 'from'
// *** HERE ***
// In the original code there is a typo (formData[1] instead of formData[0])
alert(PS.data.formData[0].setDef[0].Name);
//expected id 1
alert(PS.data.formData[1].id);
//expected name 'to'
alert(PS.data.formData[1].setDef[1].Name);
You just referenced PS.item twice in this part of your code:
PS.item.Name = "From";
PS.item.Type = "STRING";
PS.setDef.push(PS.item);
alert(PS.setDef[0].Name);
//changing the value of PS.item
PS.item.Name = "To";
PS.item.Type = "STRING";
PS.setDef.push(PS.item);
alert(PS.setDef[1].Name);
You can chnage your code this way and go happy with the results:
//creating first instance
PS.item = {};
PS.item.Name = "From";
PS.item.Type = "STRING";
PS.setDef.push(PS.item);
alert(PS.setDef[0].Name);
//creating the second instance
PS.item = {};
PS.item.Name = "To";
PS.item.Type = "STRING";
PS.setDef.push(PS.item);
alert(PS.setDef[1].Name);
Got the idea?
There are 2 things here.
First for id, change the code to the following,
PS.data.formData.push({"id":++PS.id, "setDef":[PS.setDef[0]]});
PS.data.formData.push({"id":++PS.id, "setDef":[PS.setDef[1]]});
Since your id starts with -1 when u assign id++ to id, it firsts assigns the value currently in id and then increments the value of id, hence you get -1 and 0.
Second, when you push PS.item, you are actually passing the reference to the object and not the actual object. Hence when you are updating the value of PS.item, it gets reflected in both the places. Try to create a new object and push it, instead of overwriting the old one.
Use PS.item = {}; to create a new object, before assigning the values. This should work.

How to access elements inside nested objects in a Javascript loop using variable names?

I'm clueless. I have a JSON string like this which I need to check for a supplied "property" (postsome in the following example):
var index_file =
[{
"indexAB":[
{ "postsome": ["keyword_abc", "keyword_def"] },
{ "testsome": ["keyword_111", "keyword_222"] }
]
},{
"index_random": [
{ "postsome": ["keyword_abc"] }
]
}]
There my be any number of indices ("indexAB", "index_random") with n objects inside.
I need to "find" my property postsome but I cannot get it to work, because I'm struggling with the correct way of accessing the object.
So:
for (var i = 0, l = indices.length; i < l; i += 1) {
doc._id = "postsome",
index_name = "indexAB";
indices[i]["indexAB"]; // ok, returns object on correct iteration
indices[i][index_name]; // undefined
indices[i].indexAB[0][doc._id] // ok, returns undefined or keywords
indices[i][index_name][0][doc._id] // undefined
}
Question:
How can I access a nested object in loop using a variable name index_name?
This is not a direct answer to your question but I believe that it may actually help you more than giving you a complicated way to access values in your object.
If instead of this JSON object:
var index_file =
[{
"indexAB":[
{ "postsome": ["keyword_abc", "keyword_def"] },
{ "testsome": ["keyword_111", "keyword_222"] }
]
},{
"index_random": [
{ "postsome": ["keyword_abc"] }
]
}];
you would have this much simpler data structure:
var index_file =
{
"indexAB": {
"postsome": ["keyword_abc", "keyword_def"],
"testsome": ["keyword_111", "keyword_222"]
},
"index_random": {
"postsome": ["keyword_abc"]
}
};
then it would be much easier to access, using just:
var value = index_file.indexAB.postsome[0]; // no loops, no nothing
// value == "keyword_abc"
See: DEMO
I think that what you should change is your data model because currently it is something that is very far from the idea of JSON and it will always be very hard do access data in it.
A couple of issues
"indexAB" only exists on the first element in the array
you cannot have dots inside variable names.
I suggest you test whether indexAB is a property of the object before deferencing it further. See example below:
Fixed
var indices = index_file;
for (var i = 0, l = indices.length; i < l; i++) {
var doc_id = "postsome";
var index_name = "indexAB";
indices[i]["indexAB"]; // ok, returns object on correct iteration
indices[i][index_name]; // undefined
if ("indexAB" in indices[i]) {
indices[i].indexAB[0][doc_id] // ok, returns undefined or keywords
indices[i][index_name][0][doc_id] // undefined
}
}
index_name is undefined because the line prior to that raises an error
doc._id = "postname" // this causes an error
Just use a simple string
doc = "postname"

Categories