javascript for loop and array pushing [duplicate] - javascript

This question already has answers here:
Array.push() makes all elements the same when pushing an object [duplicate]
(2 answers)
Dates changing when I change another date [duplicate]
(1 answer)
Closed 26 days ago.
I'm trying to create an array of date objects starting from a certain date up till today.
Here's the code I have:
var beginning = new Date("04,06,2013");
var dates = [];
var today = new Date();
while (beginning < today){
var x = beginning;
console.log(x);
dates.push(x);
beginning.setDate(beginning.getDate()+1)
}
for (var i in dates) {
console.log(dates[i]);
}
In the while loop I see the correct dates incrementing but when I print out the dates in the array at the last for loop I see all the dates that are pushed being today's date.
Any ideas?

What your code does is push a whole bunch of references to the exact same Date object. So, you have an array full of all the same Date object and each time you change that object, all elements in the array just point to the same object so they will all appear to change.
When you push an object into an array or assign an object to a variable, it does not make a copy, it pushes a reference to it (think of it like a pointer in other languages). To push different date objects for each iteration of the loop, you'd have to create a new date object each time through the loop and push that.
In javascript, assigning an object or an array to any variable (which includes pushing it into an array) only assigns a reference to that object or array, not a copy. This is a common issue that bits most people coming up to speed on javascript.
You can make a new date object each time through the loop like this:
var beginning = new Date("04,06,2013");
var dates = [];
var today = new Date(), x;
while (beginning < today){
x = new Date(beginning.getTime());
console.log(x);
dates.push(x);
beginning.setDate(beginning.getDate()+1)
}

You're only working with one single Date instance throughout all that code.
To create a copy of a Date, do this:
x = new Date(beginning.getTime());
Then call the .setDate() method to move it forward.
The setters on JavaScript Date instances change the object. They don't create a new one.

Related

Javascript overwrites the array in several places within an object [duplicate]

This question already has answers here:
Modifying a copy of a JavaScript object is causing the original object to change
(13 answers)
Closed 3 months ago.
Sorry for the strange title, but I've come across an issue that is plain weird. To give some background, i'm working on a booking system that takes a time range as an input from admin, generates available times based on it, and then reduces the available times based on already made bookings (i.e admin specifies availability from 10:00 to 12:00, booking has been made to 11:30, available times will be times = [10:00, 10:30, 11:00, 12:00]).
I have an object that contains per month for each day the available times.
availableTimesPerDay: {
1: ["10:00","10:30","11:00","11:30","12:00"],
2: ["10:00","10:30","11:00","11:30","12:00"],
3: ["10:00","10:30","11:00","11:30","12:00"],
....
}
Where the number represents the date for the given month.
Bookings are represented as an array of objects, format is:
bookedTimes = [
{
date: "2022-12-01T11:30:00.000+02:00"
}
];
I planned to have a function which would iterate through each booking and remove the availability for that time on a given date (based on example above, 11:30 would need to be removed from availableTimesPerDay[1] leaving the value for it as ["10:00","10:30","11:00","12:00"]
The function itself is defined as such:
function reduceAvailableTimesBasedOnDateTime(availableTimesPerDay,bookedTimes){
console.log(JSON.stringify(availableTimesPerDay));
bookedTimes.forEach((bookedDateObject) => {
let bookedDate = new Date(bookedDateObject.date);
// 1
let currentAvailableTimesOnDate = availableTimesPerDay[bookedDate.getDate()];
// ["10:00","10:30","11:00","11:30","12:00"]
let bookedTime = bookedDate.toLocaleTimeString('et');
// "13:30:00"
let time = bookedTime.substring(0,bookedTime.length - 3);
// "13:30"
let index = currentAvailableTimesOnDate.indexOf(time);
// 3
if (index > -1) {
currentAvailableTimesOnDate.splice(index, 1);
// ["10:00","10:30","11:00","12:00"]
}
})
console.log(JSON.stringify(availableTimesPerDay));
return availableTimesPerDay;
}
The way I understand this function is that i've extracted a specific array of available times into a new variable and removed a specific time from that array. I have done no modifications on an original data and I would expect at this stage the availableTimesPerDay to remain unmodified. However, when I run my code, the availableTimesPerDay is modified even though I do no operations with availableTimesPerDay object itself.
What's even stranger is that the modification is not just strictly done on the 1st element, but on all specific dates that have the same day of the week. Here's output from the console for the console.log(availableTimesPerDay) defined in the function (note that 11:30 value is removed on dates 1st of December, 8th of December, 15th of December etc.
booking-helper.js:94 {"1":["10:00","10:30","11:00","11:30","12:00"],"2":[],"3":[],"4":[],"5":[],"6":[],"7":[],"8":["10:00","10:30","11:00","11:30","12:00"],"9":[],"10":[],"11":[],"12":[],"13":[],"14":[],"15":["10:00","10:30","11:00","11:30","12:00"],"16":[],"17":[],"18":[],"19":[],"20":[],"21":[],"22":["10:00","10:30","11:00","11:30","12:00"],"23":[],"24":[],"25":[],"26":[],"27":[],"28":[],"29":["10:00","10:30","11:00","11:30","12:00"],"30":[],"31":[]}
booking-helper.js:105 {"1":["10:00","10:30","11:00","12:00"],"2":[],"3":[],"4":[],"5":[],"6":[],"7":[],"8":["10:00","10:30","11:00","12:00"],"9":[],"10":[],"11":[],"12":[],"13":[],"14":[],"15":["10:00","10:30","11:00","12:00"],"16":[],"17":[],"18":[],"19":[],"20":[],"21":[],"22":["10:00","10:30","11:00","12:00"],"23":[],"24":[],"25":[],"26":[],"27":[],"28":[],"29":["10:00","10:30","11:00","12:00"],"30":[],"31":[
What's even more interesting is that if I copy the same function to codepen with same data or call it directly from the browsers console it works as expected - it removes the specific time from a specific date.
The way I understand this function is that I've extracted a specific array of available times into a new variable and removed a specific time from that array. I have done no modifications on an original data and I would expect at this stage the availableTimesPerDay to remain unmodified.
But that's not what is happening. A mere assignment of an array to a new variable does not create a new array. The new variable will reference the same array. So whatever mutation you bring to that array will be visible whether you look at that array via currentAvailableTimesOnDate or via availableTimesPerDay[bookedDate.getDate()]: they are just different ways to see the same array object.
If you don't want that splice to affect availableTimesPerDay[bookedDate.getDate()], then you must take a copy:
let currentAvailableTimesOnDate = [...availableTimesPerDay[bookedDate.getDate()]];
What's even stranger is that the modification is not just strictly done on the 1st element, but on all specific dates that have the same day of the week.
This would suggest that you have initialise availableTimesPerDay with a similar misunderstanding, so that all entries in that array reference the same array. This could for instance happen when you had initialised it as follows:
let availableTimesPerDay = Array(7).fill( ["10:00","10:30","11:00","11:30","12:00"]);
This creates one array ["10:00","10:30","11:00","11:30","12:00"] and populates the outer array with duplicate references to that array.
You should solve that too, and do something like this:
let availableTimesPerDay = Array.from({length: 7}, () =>
["10:00","10:30","11:00","11:30","12:00"]
);
Now that array literal is evaluated 7 times, each time producing a new array.
It seems like you might be under the mistaken assumption that this code:
let currentAvailableTimesOnDate = availableTimesPerDay[bookedDate.getDate()];
makes a copy of the array and you are then operating on the copy, not the original array. But that's not the case. You're essentially just aliasing the same array and then operating on it. To demonstrate:
const availableTimesPerDay = {
1: ["10:00","10:30","11:00","11:30","12:00"],
2: ["10:00","10:30","11:00","11:30","12:00"],
3: ["10:00","10:30","11:00","11:30","12:00"],
};
const currentAvailableTimesOnDate = availableTimesPerDay[1];
currentAvailableTimesOnDate.splice(0, 100);
console.log(availableTimesPerDay[1]);
If you run this code in the browser console, it will log an empty array, even though you "do no operations with availableTimesPerDay object itself."
To copy the array, you have at least a few options:
const currentAvailableTimesOnDate = availableTimesPerDay[1].slice();
// OR
const currentAvailableTimesOnDate = [...availableTimesPerDay[1]];
// OR
const currentAvailableTimesOnDate = Array.from(availableTimesPerDay[1]);
Using any of the above code, you would then be operating on a copy of the array, not the original one.
Regarding the day-of-week thing, that sounds to me like you are using getDay() instead of getDate() somewhere, though I do not see that in your code, and in fact you say you do not see that in the browser console. I don't have a clear answer for that but could it be that at one point you had getDay() and you are accidentally running an older version of the code that is different from what you are showing here and testing in the console?

Javascript combine and sort arrays

Beginner
I have 3 arrays, i would like to combine and sort, according to date and time.
All 3 arrays, only have date and time values.
Example:
var slackStart = []; //time the current starts for the week.
var CurrentTurn = []; //time the current turns for the week.
var slackStop = []; //time the current stops for the week.
Output slackStart (contains all starting times for the week):
[ "2017-10-24T03:15:36Z", "2017-10-24T09:13:44Z", "2017-10-24T15:41:27Z", "2017-10-24T21:40:27Z", "2017-10-25T03:47:20Z"]
I need to combine the 3 arrays and sort according to date and time. I also need to know from which array the value came. If its slackStart, i know its the starting time for the current.
I want to display it like this.
Current start: 11/11/17 12:00
Current turn: 11/11/17 14:00
Current Stop: 11/11/17 17:00
Combining the arrays is easy but how can i know from which array it came?
I tried using keys but struggled a bit.
Any help would be appreciated.
You can combine arrays simply by calling the 'concat' method:
var aryA = [1,2,3]
,aryB = [4,5,6]
,aryResult = aryA.concat(aryB);
'aryResult' will contain [1,2,3,4,5,6], in terms of identifying where it came from, are the dates going to be unique?
If not then you should forget an array and convert to an object with unique key for each entry, then you can simply use the key.
var objResult = {};
for( var idx in aryResult ) {
objResult["k" + idx] = aryResult[idx];
}
The above will translate the combined array into an object with each member having a key that starts with k followed by the array index.

Transform values in JavaScript array to values in an array [duplicate]

This question already has answers here:
From an array of objects, extract value of a property as array
(24 answers)
Closed 5 years ago.
Let's say I have the following Object.
const result = [{date:'2016-11-21',name:'Bob',score:0.1034947}{date:'2016-10-21',name:'Bill',score:0.2081911},{date:'2016-10-21',name:'Mary',score:0.234947},{date:'2016-10-21',name:'Bob',score:0.1034947},{date:'2016-11-21',name:'Bill',score:0.2081911},{date:'2016-11-21',name:'Mary',score:0.234947},{date:'2016-12-21',name:'Bob',score:0.1034947},{date:'2016-12-21',name:'Bill',score:0.2081911},{date:'2016-12-21',name:'Mary',score:0.234947}];
What I want to take that object and turn those values and put them in separate arrays. So for example,
dateArray = ['2016-11-21','2016-10-21', ....]
I am really quite new to JavaScript. I am trying to do it with map but not sure if I am on the right track. So thanks in advance!
var dateArray = [];
for (var index in result) {
var item = result[index];
dateArray.push(item.date);
}
You can use Array.prototype.map to transform your array to a new one by projecting every original value with the defined function.
var dateArray = result.map(function(r) {
return r.date;
});
This code literally means "take array result and make a new array dateArray of the same length where every item is a value of date property of corresponding item of result".
You can also use arrow-function, but it is only compatible with ECMAScript 6.
var dateArray = result.map(r => r.date);

Display specific parts of array

This code is creating an array, dateArray, from the parameter, date3, which is being passed through a function.
The data being passed through that function is a full date in the format, "12312015". The variable month should break off the first two characters of the array, dateArray. Then the variable Smonth converts the month array back into a string. The last line is then supposed to display the string "12" through the HTML form in a textbox. When the button on the form is pressed the function runs but it displays nothing.
var dateArray = [date3];
var month = dateArray.slice(1, 2);
var Smonth = month.toString();
VerifyForm.dobBox.value = Smonth;
The problem is you are creating an array dateArray with only 1 item in it which is the date string, so slicing it from 1 to 2 will return an empty array not the first and second characters of the original string.
Since date3 is a string, you can use String.substring() to extract the first 2 characters
var month = date3.substring(0, 2);
VerifyForm.dobBox.value = month;
After this
dateArray = [date3];
the dateArray contains single element at index 0. And here
dateArray.slice(1, 2);
you are trying to get range from 1 to 2 elements. But they are not there.
So you are getting nothing - empty array.
The dateArray you're creating is an array with a SINGLE value.
the slice function you're using is used to 'slice' up arrays with MULTIPLE values.
To achieve what you're trying to achieve you need to use substring.
Example:
VerifyForm.dobBox.value = date3.substring(0,2);

storing a dynamic array of values inside an object looped within a for statement

I am looking to create a set of dynamically created arrays stored inside an object. the outcome would be something similar to this...
object.array0.length = 5, object.array1.length = 4, etc
the name of the array would be generated from within a for loop based on a numerical value declared elsewhere in the application.
Here is the code that I have...
var obj = {};
var weekNum = 4;
for(i=0; i < weekNum.length;i++) {
obj['week'+i] = [];
obj['week'+i].push(day);
console.log('days stored in week0: '+obj.week0.length);
}
What seems to be happening is that obj['week'+i] doesn't realize that it is an array, and the push command doesn't seem to be enough to make it think so. So as a resulting value of obj.week0.length is always 1 with the actual value just being replaced each time as opposed to the array being incremented.
Also fyi,
The parameter day in the above code would be passed in from another function representing any chosen day (Mon, Tues, etc)... However, the sequence and the amount of days passed in could differ but will never exceed 5 (m-f).
Looks like a logic problem to me. You're always only inserting 1 day into the array unless day represents something else altogether.
var obj = {};
var weekNum = 4;
// var was missing :)
for(var i = 0; i < weekNum.length; i++) {
// check if entry exists before creating new.
obj['week'+i] = obj['week'+i] || [];
// you're always only inserting 1 value inside the week array
// don't you want to loop through the number of days
// and insert a day entry for *this* week for each day. like this?
// days is another array of, hmm.. days
for(var j = 0; j <days.length; j++) {
obj['week'+i].push(days[j]);
}
console.log('days stored in week0: '+obj.week0.length);
}
It is not changing, because each time through the loop you reset the value to [], then push onto it. Try moving the obj['week'+i] = [] to outside the loop.

Categories