Accessing Properties in Array of Arrays? (Javascript) - javascript

var person = { firstname: "", lastname: "", email: "" };
var student = Object.create(person);
var i = 0;
var flag = true;
//create array of arrays. similar to a database. Receive unspecified number
//number of inputs from user
while (flag) {
var input = prompt("Please enter fname, lname, and email");
//Sample input: John, Doe, abcd#efg.com
var results = input.split(", ");
student[i]=({
firstname: results.shift(),
lastname: results.shift(),
email: results,
});
i++;
console.log(student[i].firstname);//testing code. returns student[i] is undefined
console.log(student[0].firstname);//testing code. returns John.
flag = confirm("Do you want to continue?");
};
When I try to run this code I get the error student[i] is undefined.
Even though I pretty much set the values of student[i] in the code directly above it.
However, when I try to output student[0].firstname I will get John.
EDIT: Even with
console.log(student[i].firstname);
placed in front of the i++ it isn'tworking

You're incrementing the i and then you query the array. So when you put in a new item lets say the index 0, when you query the result back, you'll actually query the student 1. Move the i++; down after the console.log.

Look at what you do:
student[i]=({
...
i++;
...
console.log(student[i].firstname);
So you set student[i]. Then you increment i, so it is no longer the same value as it was before. Then you try to use that value to access a property of student, which doesn't exist because you haven't set it.
You need to reorder your calls. I imagine i++ should be at the very end of the block.

After you assign student[i] you call i++. This sets i=1. You have not set students[1] to any value.

I believe what you want to do is make a students array, and then push new instances to that.
var students = [];
var flag = true;
//create array of arrays. similar to a database. Receive unspecified number
//number of inputs from user
while (flag) {
var input = prompt("Please enter fname, lname, and email");
//Sample input: John, Doe, abcd#efg.com
var results = input.split(", ");
students.push({
firstname: results.shift(),
lastname: results.shift(),
email: results[0],
});
console.log(JSON.stringify(students)); //testing code
flag = confirm("Do you want to continue?");
};

That i++; above console.log(student[i].firstname);//testing code. returns student[i] is undefined is setting i = 1.

Move the i++ after your logging and change the way results is accessed
var results = input.split(", ");
student[i]=({
firstname: results[0],
lastname: results[1],
email: results[2]
});
console.log(student[i].firstname);//testing code. returns student[i] is undefined
console.log(student[0].firstname);//testing code. returns John.
i++;

Related

looping through collection of javascript objects

Am trying to read only very first element of friends array and add it to matches array for each object. If I add matches property directly on object. Then it returns expected result. But if I use a function addmatches to add matches array property. Then matches array value is coming same for each animal object.
var AnimalCreator = function(username, species, tagline, noises) {
var friends = [];
//var matches = [];
return {
username: username,
species: species,
tagline: tagline,
noises: noises,
friends: friends,
//matches: matches
}
};
var sheep = AnimalCreator('Cloud', 'sheep', 'You can count on me!', ['baahhh', 'arrgg', 'chewchewchew']);
var rabbit = AnimalCreator('Sky', 'Rabbit', 'I like jumping!', ['haha', 'heehee']);
var tiger = AnimalCreator('Tim', 'Tiger', 'I am strong!', ['Grrrr', 'grrrrrr!']);
var bear = AnimalCreator('Poo', 'Bear', 'I am your friend', ['wowo', 'whwhwh']);
var addFriend = function(animal, friend) {
animal.friends.push(friend.username);
};
addFriend(sheep, rabbit);
addFriend(sheep, tiger);
addFriend(tiger, bear);
var myFarm = [sheep, rabbit, tiger, bear];
var addmatches = function(farm){
var matches = [];
for(var i=0;i < farm.length; i++){
farm[i].matches = matches;
}
};
addmatches(myFarm);
var giveMatches = function(farm) {
for (var i = 0; i < farm.length; i++) {
if (farm[i].friends.length > 0) {
farm[i].matches.push(farm[i].friends[0]);
}
}
};
giveMatches(myFarm);
console.log(myFarm);
matches is a reference to an empty array and your code is assigning same reference for every farm object ( farm[i].matches = matches; ), you can try by assigning empty array directly like
farm[i].matches = [];
Your commented code: The function AnimalCreator is creating a new array instance on every call and every animal object is referencing to a unique array, that's why when you directly add matches, it works as expected.
Hope this will help!
This is because array is passed by referance, so every farm object is pointing to the same array by this "farm[i].matches = matches;". To fix this you can do multiple tihings.
Change "farm[i].matches = matches;" to "farm[i].matches = [];" (Best option as of now).
Move "var matches = [];" inside for loop and use "let" insted of "var".

localStorage only saves first member of array

Every time I want to get the array from localStorage it only gets me the last value.I think it handles the array as a object. How do I fix this?
function saveData() {
if ($("#forma").valid() == true) {
var Name = document.getElementById("username").value;
var Year = document.getElementById("godinaupisa").value;
var Index1 = document.getElementById("brindeksa").value;
console.log(Name);
var EMial = document.getElementById("email").value;
var OBJ = { NAME: "JOHN DOE", YEAR: "18", INDEX1: "1", EMAIL: "#" };
OBJ.NAME = Ime1;
OBJ.YEAR = Year;
OBJ.INDEX1 = Index1;
OBJ.EMAIL = EMial;
var arrayOBJ = [];
arrayOBJ.push(OBJ);
localStorage.setItem("ARRAY", JSON.stringify(arrayOBJ));
alert("saved");
$("#forma").resetForm;
};
}
So, you're calling setItem which will just set it to whatever you pass it. I think what you want to go is read the current value, append to that and set the new value to be that.
var data = localStorage.getItem("ARRAY");
data = JSON.parse(data);
data.push(OBJ);
localStorage.setItem("ARRAY", data);
Because you create the arrayOBJ array each time you try to save, you're only ever going to have one item inside of it. And when you save it to localstorage you're just writing over anything that was already there. Instead try defining arrayOBJ outside your save function as a global variable.
Alternatively you can use localStorage.getItem and JSON.parse to get the current array that's in localStorage before pushing to it.

Javascript: Using user input to search an array of arrays

Maybe I'm structuring this code wrong (first time working with Javascript) but I want to take user input and search an array of arrays to check if an array with that name exists.
I first tried using the eval() function which I've been told isn't good but it works when there is a match, failing when a match that doesn't exist though.
The basic premise of the program is there is an array containing locations which are subsequently arrays containing food items. The user enters the name of a food item and where they want to put it and it will create an object of food, insert that object into the right location within the arrays, and also input the item onto a list displayed in html.
Here's all the code so far:
var fridge = [];
var freezer = [];
var pantry = [];
var locations = [fridge, freezer, pantry];
function Food(name, location, locationName){
this.name = name;
this.location = location;
this.locationName = locationName;
this.displayName = function(){
alert(this.name);
};
};
function createFood(){
var name = prompt("Enter the items name:");
var locationName = prompt("Enter a location to store it:")
var location = eval(locationName);
while(locations.indexOf(location) == -1){
alert("This is not an actual location.");
locationName = prompt("Please enter another location:");
location = eval(locationName);
};
var x = new Food(name, location, locationName)
function insertFood(Food){
var a = locations.indexOf(Food.location);
locations[a].push(Food);
var list = document.getElementById(Food.locationName + "_items");
var li = document.createElement("li");
li.innerHTML = Food.name;
list.insertBefore(li, list.lastChild);
};
insertFood(x);
};
Please let me know if this is structured wrong cause this was my idea for structuring at first glance.
Thanks!
As suggested above, it would be best to make locations an object, so that you can have a key (a string) pointing to the array with the same name.
var fridge = [];
var freezer = [];
var pantry = [];
var locations = {
"fridge":fridge,
"freezer":freezer,
"pantry":pantry
};
The benefit of this is that you don't need to have a locationName, since it never really comes into play. All you would need is to check if the locations object has a property by the same name as the user input, using the native hasOwnProperty function. Something like:
if(!locations.hasOwnProperty(userInputLocation))
alert("That is not a designated location");
Then your Food constructor also becomes simpler, and needs only name and location properties:
function Food(name, location){
this.name = name;
this.location = location;
}
You can also then call any specific location directly by its name (if you're going to declare it globally as you did in your code), or more appropriately (if you declare the arrays inside the object as in SGD's code) by locations[location], where location is just a string holding either "freezer" or "pantry" or "fridge". You can also call the array via locations[someFood.location].
Anyway I am not much for prompts and alerts (let alone eval), so I created a jsBin using input fields, you can check it out here: http://jsbin.com/pamoquwuhu/1/edit
edited to add:
If the goal is that you later want to find food by its name in all the locations it is saved in, it would be best to add/push foodObj.name instead of the whole foodObj in locations[location]. Then you can use the native for(property in object) loop on the locations object to see where all a given food might be stored, and push it into a results array. So your findFood function might contain the following (assuming food is the user input string of of food name to search for:
var results = [];
for(var loc in locations){ // loops through the property names in `locations`
if(locations[loc].indexOf(food)>=0)
results.push(loc);
}
if(!results.length){
alert(food+' was not found');
else
alert(food+' was found in '+results.toString());
Assuming the same food can be stored in multiple locations and that you want to find a given food by its name, your food object's location property would become less important (or possibly useless).
You are using Food as function/constructor and as parameter name (that should not be the issue however but can cause trouble later) and you are never calling insertFood. Also locations should rather be object than array so that you can access the sub arrays as you do in your code.
var locations = {fridge : [], freezer:[], pantry:[]];
function Food(name, locationName){
this.name = name;
this.locationName = locationName;
this.displayName = function(){
alert(this.name);
};
};
function createFood(){
var name = prompt("Enter the items name:");
var locationName = prompt("Enter a location to store it:")
while(locationName in locations){
alert("This is not an actual location.");
locationName = prompt("Please enter another location:");
};
var x = new Food(name, locationName)
function insertFood(food){
locations[food.locationName].push(food);
var list = document.getElementById(food.locationName + "_items");
var li = document.createElement("li");
li.innerHTML = food.name;
list.insertBefore(li, list.lastChild);
};
// call the method now?
insertFood(x);
};
createFood();

Parse - Javascript Nested Calls

I am writing a javascript code using Parse. I have User class and Subscription class. All users' subscription information are stored on Subscription class so it is like one to many relationship.
I would like to retrieve user information and each user's subscription count and store it in an object array.
What I have tried is as follows:
var user = Parse.User;
var query = new Parse.Query(user);
query.find().then(function(objects) {
return objects;
}).then(function (objects) {
for(var i = 0; i < objects.length; i++) {
var object = objects[i];
var subscription = Parse.Object.extend('Subscription');
var queryForSubscription = new Parse.Query(subscription);
queryForSubscription.equalTo('subscriptionUser', object);
queryForSubscription.count().then(function(subscriptions) {
var userEmail = object.get('email');
var userDOB = object.get('userDOB');
var userJoinedAt = object.createdAt;
var userGender = object.get('userGender') ? 'Male' : 'Female';
var subscriptionCount = subscriptions;
var sub = [
userEmail,
userDOB,
userGender,
userJoinedAt,
subscriptionCount
];
userArray.push(sub);
});
}
});
However, userArray only contains last user's information repetively. I reckon it is because wihitn the second query promise (queryForSubscription).count()) runs after the outer for loop finishes.
Let's say I got User A and User B. User A has two subscriptions whereas User B has none.
What I expected is something like this:
[{User A's email, User A's dob, User A's Gender, User A's Joined Date, 2},
{User B's email, User B's dob, User B's Gender, User B's Joined Date, 0}]
However, the result is
[{User A's email, User A's dob, User A's Gender, User A's Joined Date, 2},
{User A's email, User A's dob, User A's Gender, User A's Joined Date, 0}]
I'm stuck at the moment. Have been trying to use Promise and etc but got no idea..Please help!
UPDATE
GOTTA LOVE SO!!! THANK YOU EVERY SINGLE ONE OF YOU GUYS SO MUCH!!
One more question here. Actually, I got one more class called Favourite to get a count of each user's number of favourites.
If the number of User A's favourite is 5 and 3 for User B, the expected result will look like this in the end:
[{User A's email, User A's dob, User A's Gender, User A's Joined Date, 2, 5},
{User B's email, User B's dob, User B's Gender, User B's Joined Date, 0, 3}]
I am not too sure where I put a new query for Favourite class...Need your advice again!
You can go with #Hacketo's answer.
Another hacky way to get around this bug is to use .forEach() :
}).then(function (objects) {
objects.forEach(function(object) {
var subscription = Parse.Object.extend('Subscription');
...
});
});
A new object variable will be allocated for each iteration of the loop, and you should escape the "shared var" bug.
pointing out the bug
One of the common javascript pitfalls is : a local variable's scope is not its closest bloc, it is its closest function.
The following snippet :
function (objects) {
for(var i = 0; i < objects.length; i++) {
var object = objects[i];
...
is actually equivalent to :
function (objects) {
var i, object;
for(i = 0; i < objects.length; i++) {
object = objects[i];
...
So the object variable in the OP's code is actually shared by all the created queryForSubscription variables, and when any of the .then(..) callbacks is executed (after the loop finishes, as the OP correctly pointed out), this object variable holds the value of the last item in the array.
It seem to be that you need to save the value of object when the last functions are executed. Try this :
for(var i = 0; i < objects.length; i++) {
var object = objects[i];
queryForSubscription.count().then(
(function(myObject){
return function(subscriptions) {
var userEmail = myObject.get('email');
...
};
})(object)
);
}

How to generate an array of arrays in Javascript?

So given:
var person = {name: "", address: "", phonenumber: ""}
I want to create a loop to receive user input (until they decide they don't want to input anymore information and input nothing or click cancel). I'd also like to use the person object as a prototype.
So I guess an object just to store the name/address/phone number of an arbitrary number of people. My logic for this would be to dynamically add an entire array to an object for every iteration of my loop. My code looks something like this:
var person = {name: "", address: "", phonenumber: ""}
var customer = []; //used to store each person
var input = "x";
//loop prompting user to input name/address/phone number
for(var i = 0; input != ""; i++){
var input = prompt("Input separated by commas");
//example input: mike, main, 123456789
var results = input.split(", "); //create an array from the input
//move input into the person array.
//person to look like {name = "mike", address = "main", phone = "123456789"}
person.name = results.shift();
person.address = results.shift();
person.phone = results;
customer[i] = person;//store the person array into the customer array.
}
I've been trying to dynamically generate something like this:
customer =
[{name, address, phone},
{name, address, phone},
{name, address, phone}]
and then be able to access it and print it. i've been trying to access it with
console.log(customer[0].phone);
unfortunately im getting an error.
sorry for my error, console.log prints nothing so it seems like there's nothing stored in customer[0].phone.
i can't get access to any of the data that i've prompted the user for and saved in variables. when i use the alert function all i get is a blank box. whenever i try to print customer i get the message [object Object]or something along those lines
var customer = [];//create array
var person = {};// create object
var input = prompt("...");//your prompt
var results = input.split(", "); //create an array from the input
person.name = results[0];//add result with 0 index
person.address = results[1];//add result with 1 index
person.phone = results[2];//add result with index 2
customer[0] = person;//add the person object to the array.
The above code should do as you wish. I'm having a hard time seeing why you would iterate a prompt to the same user?? So try this first then go on.
http://jsfiddle.net/zkc2swmp/1/
Don't go irratating your users with prompt boxes, use a form. Also don't iterate something like that, and your condition in the for loop basically creates an infinite loop which is also bad
My code could be a lot better, such as if conditions, and exactly how to use this with a form. Though frankly it seems as though you are far from that. So I've started you off, try it and see if you can implement this the way you want, then comment with suggestions for helping you do something else.
First of all, every time you are assigning person to customer i.e.
customer[i] = person;
all other objects are getting modified as your breaking point is input== "" so all objects are modified with null values.
in start you are defining property as "phonenumber" and in the end u r putting value in "phone".
correct code shud be :
var customer = []; //used to store each person
var input = "x";
//loop prompting user to input name/address/phone number
for(var i = 0; input != ""; i++){
var input = prompt("Input separated by commas");
//example input: mike, main, 123456789
var results = input.split(", "); //create an array from the input
var person = {};
person.name = results.shift();
person.address = results.shift();
person.phone = results;
customer[i] = person;//store the person array into the customer array.
}

Categories

Resources