Putting an object into an array in JavaScript - javascript

I'm currently working with an MVC JS framework and I want to be able to get a list of objects that I can take a random entry out of on a loop. So far I've managed to create a function that finds a random ID and pulls out that object so that part is not a problem. It's what is going into the array of objects:
QuestionsSetup: function(gameType) {
// Setup Resources
var c = this.View.children;
var player1qs = [];
var leftQ = 0;
var rightQ = 0;
var maxQValue = 50;
var minQValue = 1;
// Fill array with questions
for (var i = 0; i < 5; i++) {
// Build a random question with numbers between 1 and 50
// Build Question Text to output to user
// Generate correct answers based on generated question
// Generate unsorted, incorrect answers and add them to an array
//Place Questions into object
questions.qId = i;
questions.leftQ = leftQ;
questions.rightQ = rightQ;
questions.correctAnswer = correctAnswer;
questions.allAnswers = sortedAnswers;
questions.questionText = questionText;
//Add to array of questions
player1qs.push(questions);
}
}
This does add them to an array but when adding a new object it also changes the values of the existing objects in the array so they all come out the same no matter which one I pull out later. The questions object is declared in it's own file in a models folder. Is there any way, at the start of each loop, to tell the application I want new empty questions object as opposed to referencing the existing ones? I know that you can in similar back end languguages so I refuse to beleive that something so simple doesn't exist in JavaScript too?

Declaring a variable for each array item is definitely missing.
QuestionsSetup: function(gameType) {
// Setup Resources
var c = this.View.children;
var player1qs = [];
var leftQ = 0;
var rightQ = 0;
var maxQValue = 50;
var minQValue = 1;
// Fill array with questions
for (var i = 0; i < 5; i++) {
var tempQuestion = {
qId: i,
leftQ: leftQ,
rightQ: rightQ,
correctAnswer: correctAnswer,
allAnswers: sortedAnswers,
questionText: questionText
}
// ...
//Add to array of questions
player1qs.push(tempQuestion);
}
}
Using a separate closure inside a loop also might be a good idea.

do this:
for (var i = 0; i < 5; i++) {
let questions = {};
// the rest....
you need to define the object first.

Maybe you should just initialize the questions object before initializing its properties, so the code should look like this:
//Place Questions into object
questions = {};
questions.qId = i;
questions.leftQ = leftQ;
questions.rightQ = rightQ;
questions.correctAnswer = correctAnswer;
questions.allAnswers = sortedAnswers;
questions.questionText = questionText;
//Add to array of questions
player1qs.push(questions);

Related

How to check if data being added to an array already exists in a different array?

I am looking to create a simple script for a Google sheet in which array 1 will already be populated with a list of names. As a new name gets added to array 2, array 1 is checked for the name. If the name which was entered into array 2 is present in array 1 an action will be performed. This search function must take place each time a new name is added to array 2 to determine if it exists in array 1.
function findPlayer() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var picksRange = ss.getRange("B2:M15");
var poolRange = ss.getRange("B21:G96");
var picksPlayerName = picksRange.getValues();
var poolPlayerName = poolRange.getValues();
for (var i = 0; i < picksRange.length; i++)
for (var j = 0; j < poolRange.lenth; j++)
if (picksPlayerName[i] == poolPlayerName[j]) {
poolPlayerName[i].setBackground("red")}
else {
poolPlayerName[j].setBackground("blue");}
}
This is not a complete answer, nor does it perfectly fit your use-case, but you should be able to take it from here, or perhaps come back with another question when you have a question about a specific part of your code.
const existingNames = ["Carl", "Emma", "Sarah", "Ahmad"];
const newNames = ["Emma", "Sarah", "Isa", "Igor", "Kent"];
// go through the new names and check against existing ones
newNames.forEach(newName => {
if(existingNames.includes(newName)) {
// handle duplicates: do nothing?
} else {
// handle new names: maybe add them to the existing names?
existingNames.push(newName);
}
});
console.log('After going through all new names, the complete list of known names are: ' + existingNames);
Demo where you can play with the code and learn: https://jsfiddle.net/jonahe/11uom4cu/

Node.js array instantiation

So, I have been trying for a while now and no luck. Currently I have an associative array as based on PSN profile data:
var PROFILE = {};
PROFILE.profileData = {};
PROFILE.titles = {};
and is used like this further down in the code:
PROFILE.profileData.onlineId = profileData.onlineId;
PROFILE.profileData.region = profileData.region;
PROFILE.titles[title.npCommunicationId] = title; //For looped, can be many
PROFILE.titles[title.npCommunicationId].trophies = {};
PROFILE.titles[title.npCommunicationId].trophies = trophyData.trophies; //any where from 10 - 50+ of these, for looped
Problem is, if I want to have multiple profiles, this doesn't work as it just inserts them in the same profile. I need 'PROFILE' to be an array that has all the above elements at each index.
PROFILEarray[n].profileData = {};
PROFILEarray[n].profileData.onlineId = profileData.onlineId;
PROFILEarray[n].profileData.region = profileData.region;
Something like this is what I need^
But for the above I get this error
Cannot read property 'profileData' of undefined
Once this is complete, it's saved into a file in JSON format to then be used by PHP code I've written to insert into a db.
This is a small snippet of the json output: http://textuploader.com/5zpbk (had to cut, too bit to upload)
you must define PROFILEarray[n] as object. JavaScript objects are containers for named values. You can not set value of undefined
PROFILEarray[n] is undefined in this case. Initialize it as {}(object)
Try this:
var PROFILEarray = [];
for (var n = 0; n < 5; n++) {
PROFILEarray[n] = {};
PROFILEarray[n].profileData = {};
PROFILEarray[n].profileData.onlineId = n;
PROFILEarray[n].profileData.region = 'Region' + n;
}
alert(JSON.stringify(PROFILEarray));

Create variables based on array

I have the following array and a loop fetching the keys (https://jsfiddle.net/ytm04L53/)
var i;
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
for (i = 0; i < feeds.length; i++) {
var feed = feeds[i];
alert(feed.match(/\d+$/));
}
The array will always contain different number of keys, What I would like to do is either use these keys as variables and assign the value after the : semicolon as its value or just create a new set of variables and assign the values found on these keys to them.
How can I achieve this? so that I can then perform some sort of comparison
if (test_user > 5000) {dosomething}
update
Thanks for the answers, how can I also create a set of variables and assign the array values to them? For instance something like the following.
valCount(feeds.split(","));
function valCount(t) {
if(t[0].match(/test_user_.*/))
var testUser = t[0].match(/\d+$/);
}
Obviously there is the possibility that sometimes there will only be 1 key in the array and some times 2 or 3, so t[0] won't always be test_user_
I need to somehow pass the array to a function and perform some sort of matching, if array key starts with test_user_ then grab the value and assign it to a define variable.
Thanks guys for all your help!
You can't (reasonably) create variables with dynamic names at runtime. (It is technically possible.)
Instead, you can create object properties:
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
var obj = {};
feeds.forEach(function(entry) {
var parts = entry.split(":"); // Splits the string on the :
obj[parts[0]] = parts[1]; // Creates the property
});
Now, obj["test_user_201508_20150826080829.txt"] has the value "12345".
Live Example:
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
var obj = {};
feeds.forEach(function(entry) {
var parts = entry.split(":");
obj[parts[0]] = parts[1];
});
snippet.log(obj["test_user_201508_20150826080829.txt"]);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
You can do it like this, using the split function:
var i;
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
for (i = 0; i < feeds.length; i++) {
var feed = feeds[i];
console.log(feed.split(/[:]/));
}
This outputs:
["test_user_201508_20150826080829.txt", "12345"]
["test_user_list20150826", "666"]
["test_list_Summary20150826.txt", "321"]
Use the split method
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
feedMap = {}
for (i = 0; i < feeds.length; i++) {
var temp = feeds[i].split(':');
feedMap[temp[0]] = temp[1];
}
Yields:
{
"test_user_201508_20150826080829.txt":"12345",
"test_user_list20150826":"666",
"test_list_Summary20150826.txt":"321"
}
And can be accessed like:
feedMap["test_user_201508_20150826080829.txt"]
Here is a codepen
it is not very good idea but if you really need to create variables on-the-run here's the code:
for (i = 0; i < feeds.length; i++)
{
var feed = feeds[i];
window[feed.substring(0, feed.indexOf(":"))] = feed.match(/\d+$/);
}
alert(test_user_201508_20150826080829)
Of course you cannot have any variable-name-string containing banned signs (like '.')
Regards,
MichaƂ

accessing nested properties based on structure

Could anyone please give me an alternate syntax to the following
var id = '-JLxSeCPUCVN13FxifTY';
var ResultsContainer = results[id];
var i=0;
for(var k in ResultsContainer)
{
var TheArrayOfObjectsThatIneed = ResultsContainer[Object.keys(ResultsContainer)[i]];
console.log(TheArrayOfObjectsThatIneed);
//loop the TheArrayOfObjectsThatIneed do the processing
i++;
}
as you see in the image i have an array within an object within an object and i have no idea what the property names are but the structure is always the same {results:{id:{idthatidontknow:[{}]}}} and all i need is to access the arrays
the above code is working nicely but i am new to javescript and i was wondering if there is a nicer syntax and if i am doing it the right way
Perhaps something like this?
var id = '-JLxSeCPUCVN13FxifTY';
var ResultsContainer = results[id];
for(var k in ResultsContainer) {
if (ResultsContainer.hasOwnProperty(k)) {
var TheArrayOfObjectsThatIneed = ResultsContainer[k];
console.log(TheArrayOfObjectsThatIneed);
//loop the TheArrayOfObjectsThatIneed do the processing
}
}

JavaScript stop referencing object after pass it to a function

I know JavaScript passes Objects by reference and thus I'm having a lot of trouble with the following code:
function doGradeAssignmentContent(dtos) {
var x = 5;
var allPages = [];
var stage = new App.UI.PopUpDisplay.PopUpStageAssignmentGrader(null, that);// pass launch element
for(var i = 0; i < dtos[0].result.students.length; ++i) {
var pagesSet = [];
for(var j = 0; j < dtos[0].result.questions.length; ++j) {
var questionObject = jQuery.extend(true, {}, new Object());
questionObject = dtos[0].result.questions[j];
if(dtos[0].result.students[i].answers[j].assignmentQuestionId === questionObject.questionId) {// expected, if not here something is wrong
questionObject.answer = dtos[0].result.students[i].answers[j].studentAnswer;
questionObject.pointsReceived = dtos[0].result.students[i].answers[j].pointsReceived;
} else {
var theAnswer = findAssociatedStudentAnswer(questionObject.questionId, dtos[0].result.students[i].answers[j]);
if(theAnswer !== null) {
questionObject.answer = theAnswer.studentAnswer;
questionObject.pointsReceived = theAnswer.pointsReceived;
} else {
alert("Unexpected error. Please refresh and try again.");
}
}
pagesSet[pagesSet.length] = new App.UI.PopUpDisplay.StageAssignmentGradingPages[dtos[0].result.questions[j].questionType.charAt(0).toUpperCase() + dtos[0].result.questions[j].questionType.slice(1) + "QuestionAssignmentGradingPage"](j + 1, questionObject);
}
var studentInfo = {};
studentInfo.avatar = dtos[0].result.students[i].avatar;
studentInfo.displayName = dtos[0].result.students[i].displayName;
stage.addPageSet(pagesSet, studentInfo);
}
stage.launch();
}
First let me show you what the result (dtos) looks like so you can better understand how this function is parsing it:
The result (dtos) is an Object and looks something like:
dtos Array
dtos[0], static always here
dtos[0].result, static always here
dtos[0].questions Array
dtos[0].questions.index0 - indexN. This describes our Questions, each one is an Object
dtos[0].students Array
dtos[0].students[0]-[n].answers Array. Each student array/Object has an Answers array. Each student will have as many elements in this answers Array that there were questions in dtos[0].questions. Each element is an Object
Now what we do in this here is create this Object stage. Important things here are it has an array called "this.studentsPages". This array will ultimately have as many entries as there were students in dtos[0].students.
So we loop through this for loop disecting the dtos array and creating a pagesSet array. Here comes my problem. On the first iteration through the for loop I create this questionObject element. I also have tried just doing var questionObject = {}, but what you see now was just an attempt to fix the problem I was seeing, but it didn't work either.
So at the end of the first iteration of the outer for loop I call stage.addPageSet, this is what happens here:
var pageObject = [];
pageObject["questions"] = pageSet;
pageObject["displayName"] = studentInfo.displayName;
this.studentsPages[this.studentsPages.length] = pageObject;
if(this.studentsPages.length === 1) {// first time only
for(var i = 0; i < pageSet.length; ++i) {
this.addPage(pageSet[i]);
}
}
The important thing to take notice of here is where I add pageObject on to this.studentsPages which was an empty array before the first call. pageObject now has pageSet plus a little bit more information. Remember, pageSet was an Object and thus passed by reference.
On the next iteration of the for loop, when I hit this line:
questionObject.answer = dtos[0].result.students[i].answers[j].studentAnswer;
It goes wrong. This changes the local copy of questionObject, BUT it also changes the copy of questionObjec that was passed to addPageSet and added to the studentsPages array in the first iteration. So, if I only had 2 students coming in, then when all is said and done, studentsPages hold 2 identical Objects. This should not be true.
The problem is questionObject in the doGradeAssignmentContent function is keeping a reference to the Object created on the previous iteration and then overrides it on all subsequent iterations.
What can I do to fix this?
Thanks for the help!
With out having looked at it too closely I believe you need to change the following:
// Before:
var questionObject = jQuery.extend(true, {}, new Object());
questionObject = dtos[0].result.questions[j];
// After:
var questionObject = jQuery.extend(true, {}, dtos[0].result.questions[j]);
I didn't look too closely if there are other instances in the code where this needs to be applied, but the core concept is to utilize jQuery's deep copy to generate a duplicate of the object you do not wish to retain a reference to.

Categories

Resources