Javascript pushing only last entry in for loop to object - javascript

I have the following code to populate a viewData object:
month = 1;
year = 2019;
days = 31;
// data object for return data
var viewData = {
entries: []
};
// temp data stores
var jsonData = {};
var dict = {};
for (var i = 0; i < days; i++) {
var dArr = [year, month, i+1];
var storeDate = dArr.join("-");
dict[storeDate] = 0;
}
for (var j in rows) { // I get rows from a SQL call, it works
var fullString = formatDate(rows[j].EndTime); // this just uses a function to format a date
var theDate = fullString.split(" "); // this get a date in the format YYYY-MM-dd
dict[theDate] = dict[theDate] + rows[j].TotalDuration; // add the current duration to relevant dictionary entry
}
for (var p = 0; p < days; p++) {
// create the date string for dictionary reference
var dArr = [year, month, p+1];
var storeDate = dArr.join("-");
// populate the jsonData object
jsonData['timestamp'] = storeDate;
jsonData['duration'] = dict[storeDate];
// push the jsonData object to the viewData object
console.log('---------------------------');
console.log('Timestamp: ', jsonData['timestamp']);
console.log('Duration: ', jsonData['duration']);
viewData.entries.push(jsonData);
}
So from this code, when I print out the Timestamp and the duration in the for loop, I get the right values (E.g. "timestamp": "2019-01-04, "duration": 0). But, when I resolve and print out the viewData object, I get all entries with the timestamp value of "2019-01-31" and duration "0". These values are related only to the last iteration of the for loop.
Thus, it appears as if all entries in the viewData object are being populated only with the timestamp and duration values of the last iteration of the for look.
Why is this happening? Is there something related to how javascript works that I'm not understanding here?

Check out these two lines
jsonData['timestamp'] = storeDate;
jsonData['duration'] = dict[storeDate];
jsonData['timestamp'] and jsonData['duration'] are specific key-value pairs, and you're writing over them every time you iterate through. Then when you push it in the last line, it's only pushing a reference to the object, not the actual object. console.log doesn't happen quite as synchronously as you'd want, so sometimes by the time it's actually logging, it's only showing the updated object. You could do something like this:
jsonData[p] = {};
jsonData[p].timestamp = storeDate;
jsonData[p].duration = dict[storeDate];
Another option is making jsonData an array that you push a {timestamp, duration} object or [timestamp, duration] array into.
Also, you can turn these two lines
var dArr = [year, month, p+1];
var storeDate = dArr.join("-");
into a single line using a template string
var storeDate = `${year}-${month}-{p+1}`;

viewData.entries.push(jsonData); pushes a reference of the object "jsonData" to the array, not a copy. This means that when you alter the object jsonData, the reference that was pushed to the array will be changed as well.

Related

For Loop only adds same object every time instead of different object properties

I am writing a for loop that is iterating over an array which contains different lines in a text document.
Each iteration I am trying to pull certain parts of each of the text data lines and add them to an object, namely localinoData.
At the end of each iteration I am trying to add the localinoData object (with each object property set to a new one) to a new array.
When just adding the string found in each line the to data array (localinoDataObjArray) I get different values for each of the array. However when I now change the localinoData object properties on each iterations and try to append that changed object to the array, i get the same object in all of the array positions, e.g when I
alert(localinoDataObjArray[x].X_COORD);
for all values of x, the X_COORD is the same.
function GetlocalinoDataFromFile(localinoDataFile){
var localinoDataObjArray = new Array();
var localinoData = {
time: null,
tagID: null,
X_COORD: null,
Y_COORD: null,
Z_COORD: null,
};
var allData = localinoDataFile.responseText;
var arrayOfDataLines = allData.split('\n');
// for each iteration, get the tagID, and the co-ords(seperate) and then
// create a localinoData object and add to array
for (var i = 0; i < arrayOfDataLines.length; i++) {
if (/tag: [0-9]{22}/.test(arrayOfDataLines[i])) {
var tagID = /tag: [0-9]{22}/.exec(arrayOfDataLines[i]);
localinoData.tagID = tagID;
}
if (/[0-9]+.[0-9]{3}, [0-9]+.[0-9]{3}, [0-9].[0-9]{3}/.test(arrayOfDataLines[i])) {
XYZ_COORDS = /[0-9]+.[0-9]{3}, [0-9]+.[0-9]{3}, [0-9].[0-9]{3}/.exec(arrayOfDataLines[i]);
temp = XYZ_COORDS.toString();
temp2 = temp.split(', ');
// Here I am changing the object to new values each loop
localinoData.X_COORD = temp2[0];
localinoData.Y_COORD = temp2[1];
localinoData.Z_COORD = temp2[2];
}
// Here I am appending the newly changed object to my array
// however the same object is being added every time
// (which corresponds to the last line in the text document)
localinoDataObjArray.push(localinoData);
}
// the object values for localinoDataObjArray[0]
// and localinoDataObjArray[50] are the exact same
alert(localinoDataObjArray[20].X_COORD);
}
I expect all of the array values to be different corresponding to the different lines in the text document. However all of the array values are the same (which equal the expected result of iteration over the last line in the text document).
I am very confused as when i = 0, it should be adding an object that has the values of the first line in my text document, however it shows the values i would expect from the last line in the document.
This is very strange to me and seems like a looping problem? I am very confused and would appreciate any help in this matter.
They are all references to the same object which you keep overwriting.
Try and make a fresh instance of localinoData in every iteration of your for loop.
function GetlocalinoDataFromFile(localinoDataFile){
var localinoDataObjArray = new Array();
var allData = localinoDataFile.responseText;
var arrayOfDataLines = allData.split('\n');
// alert(arrayOfDataLines[4]);
// for each iteration, get the tagID, and the co-ords(seperate) and then create a localinoData object and add to array
for (var i = 0; i < arrayOfDataLines.length; i++) {
var localinoData = {
time: null,
tagID: null,
X_COORD: null,
Y_COORD: null,
Z_COORD: null,
};
if (/tag: [0-9]{22}/.test(arrayOfDataLines[i])) {
var tagID = /tag: [0-9]{22}/.exec(arrayOfDataLines[i]);
localinoData.tagID = tagID;
}
if (/[0-9]+.[0-9]{3}, [0-9]+.[0-9]{3}, [0-9].[0-9]{3}/.test(arrayOfDataLines[i])) {
XYZ_COORDS = /[0-9]+.[0-9]{3}, [0-9]+.[0-9]{3}, [0-9].[0-9]{3}/.exec(arrayOfDataLines[i]);
temp = XYZ_COORDS.toString();
temp2 = temp.split(', ');
localinoData.X_COORD = temp2[0];
localinoData.Y_COORD = temp2[1];
localinoData.Z_COORD = temp2[2];
}
localinoDataObjArray.push(localinoData);
}
alert(localinoDataObjArray[20].X_COORD);
}

How to print localStorage array in html for loop?

I have an array in my localStorage which contains ["January","Febuary"]
I want it to be displayed in HTML preferably like this:
Month
January
Febuary
So I've tried this code:
function show(){
for(let i = 0;i < localStorage.length;i++){
var date = JSON.parse(localStorage.getItem("date"));
}
for(var b = 0; b < nameLength; b++){
document.getElementById('storageOut').innerHTML = date[b];
console.log(date[b]);
}
}
My code above does work however, the line "document.getElementById('storageOut').innerHTML = date[b];"only prints out the last data in the array, but when i check the console it prints out both.
You create the variable date in the first for-loop and assign it to one value each iteration. Easiest way would probably be to do it in a single for-loop instead:
function show(){
for(let i = 0;i < localStorage.length;i++){
var date = JSON.parse(localStorage.getItem("date"));
document.getElementById('storageOut').innerHTML = date;
}
}
Although, if you want all the dates, you should probably append it to the innerHtml:
...innerHTML += date;
Or rather:
...innerText += date;
Assuming your contents are stored in local storage key named data. Try the following.
const data = JSON.parse(localStorage.getItem('data'))
data.forEach(item => {
document.getElementById('storageOut').innerHTML += item
})

Cannot extract hours from mongodb date array

I am sucessfully getting data in date format into webservice based on NodeJS+MongoDB. But I cant extract hours from it.
This is date looks in MongoDB:
I try to either split the array elements or apply Date.getHours method using forEach loop.
The problem is that when I just console log elements in forEach loop, I can see my comment I wrote in only the last element in array which I suppose means that forEach loop does not go through all the elements in the array.
This is the code:
user.TrainingPlan[req.params.object].time.forEach(function(item, index, array)
{
console.log(user.TrainingPlan[req.params.object].time.toString() + ' xxx');
});
This is the output I get:
I fixed it by splitting date format instead. Here is the code:
var timestamps = user.TrainingPlan[req.params.object].time;
var tlength = timestamps.length;
for(var i=0; i<tlength;i++){
var dateInfo = timestamps[i].toLocaleString()
var splittedData = dateInfo.split(' ');
var yearMonthDay = splittedData[0];
var data2 = yearMonthDay.split('-');
var year = data2[0];
...
}

Read through JSON number array using javascript loop [duplicate]

This question already has answers here:
Loop through an array in JavaScript
(46 answers)
Closed 5 years ago.
I`m trying to write a loop that will read through a nested number array.
The JSON file that I`m reading goes like this. each number key represents event dates.
json reference for startdate and end date
enter image description here
I have below javascript code that reads per var i = 1 or j = 1.
I`d like to read through entire nested number from dates and store them somewhere.
$(document).ready(function () {
$.getJSON('http://app.toronto.ca/cc_sr_v1_app/data/edc_eventcal_APR?limit=500', function (data) {
var data = data;
var i = 2;
var obj = data[i].calEvent;
var bingname = obj.eventName;
var j = 1;
var startdate = obj.dates[j].startDateTime;
var time = new Date(startdate);
var starttime = time.getFullYear()+'-' + (time.getMonth()+1) + '-'+time.getDate();
var name = JSON.stringify(bingname);
document.getElementById("bingname").innerHTML = name;
document.getElementById("bingtime").innerHTML = starttime;
var name = firebase.database().ref("/bing").set({
EventName : name,
EventStart : starttime
});
});
});
Now, I should use something of incremental loop for var j. But I'm not sure how.
The problem for me is that json retrieved in obj.dates[j] doesn't seem like an array. I can't seem to read it as list of numbers to read through. Help is much appreciated.
If anyone can even sort this nearest to furthest from today's date that'd be Einstein:)
You will get an array of objects, that includes a callEvent object that has a dates property which is an array with objects with the property's startDateTime and endDateTime.
It will look like following:
[
{
callEvent: {
dates: [
{startDateTime: '', endDateTime: ''},
// more objects with start- and endDateTime
]
}
},
// more callEvent objects..
]
Now your code should loop through the array to get all callEvent objects and loop through all dates objects inside each callEvent.
$(document).ready(function () {
$.getJSON('http://app.toronto.ca/cc_sr_v1_app/data/edc_eventcal_APR?limit=500', function (array) {
// loop through all elements in the array
for (var i = 0; i < array.length; i++) {
// loop through all dates inside the array
for (var j = 0; j < array[i].calEvent.dates.length; j++) {
console.log(array[i].callEvent.dates[j].startDateTime)
console.log(array[i].callEvent.dates[j].endDateTime)
}
}
});
});
Assuming the dates are valid JSON (JSON Validator), then you should just be able to get the data and loop through it:
for (var i=0;i<data.length;++i) {
console.log(data[i].startDateTime);
console.log(data[i].endDateTime);
}

Google Script (Forms) - Cannot Convert Array to Choice[]

I have looking into this issue for a while, but have yet to find a suitable answer (most involve switching to setChoiceValues() rather than addressing the "Cannot convert Array to Choice[]" issue with setChoices([])).
While attempting to generate form sections and questions via Google Script, I ran into the issue of not getting my answer selections to go to specific pages based on the user's answer. This appears to be the difference between setChoiceValues() and setChoices([]), with the latter allowing for page navigation as best as I can tell.
However, when attempting to put my array of new choices into setChoices([]), I get the error message "Cannot convert Array to Choice[]". My code works fine otherwise, but I need to use setChoices([]) (it seems) in order to get the page navigation that I want.
How can I loop values into an array or other container and be able to make them appear as a Choices[] object? How can I make something like this work? It seems like it should be much easier than it is, but I cannot see the solution.
Below is a segment of my code that is causing the issue:
//Form - globally accessible
var f = FormApp.openById(f_id);
//Date Iterator
var curr_date = 0;
//Time Iterator
var curr_time = 0;
//Array of Times
var Tchoices = [];
//Setting Time choices per date
while(curr_date < dates.length)
{
Tchoices = [];
curr_time = 0;
//dates is an array of objects with both d's (single date) and t's
// (array of times for that date)
var d = dates[curr_date].d;
var end_break = f.addPageBreakItem().setTitle("Times for " + d);
var f_time = f.addMultipleChoiceItem().setTitle(d);
while(curr_time < dates[curr_date].t.length)
{
end_break = end_break.setGoToPage(FormApp.PageNavigationType.SUBMIT);
Tchoices.push(f_time.createChoice(dates[curr_date].t[curr_time], end_break).getValue());
curr_time++;
}
f_time.setChoices([Tchoices]);
}
There was some minor issues with the building of your MultipleChoise object:
//Form - globally accessible
var f = FormApp.openById('someID');
//Date Iterator
var curr_date = 0;
//Time Iterator
var curr_time = 0;
//Array of Times
var Tchoices = [];
//Setting Time choices per date
while(curr_date < dates.length)
{
Tchoices = [];
curr_time = 0;
//dates is an array of objects with both d's (single date) and t's
// (array of times for that date)
var d = dates[curr_date].d;
var end_break = f.addPageBreakItem().setTitle("Times for " + d);
var f_time = f.addMultipleChoiceItem();
f.addMultipleChoiceItem().setTitle(d);
while(curr_time < dates[curr_date].t.length) //verify this while not sure what you have inside your dates array
{
end_break = end_break.setGoToPage(FormApp.PageNavigationType.SUBMIT);
Tchoices.push(f_time.createChoice(dates[curr_date].t[curr_time])); //You cannot add a pagebreak inside the elements of a choiseItem array
curr_time++;
}
Logger.log(Tchoices);
f_time.setChoices(Tchoices);
}
Check the values for dates[curr_date].t.length inside the Loop I'm not sure how you constructed the array.
You cannot add a pagebreak inside the elements of a choiseItem array

Categories