sending signal on when for/in loop has completed all iterations - javascript

I have an array of objects which I am using a for/in loop to manipulate into key/value pairs, which as it works writes each to a database.
My app is designed to send a push notification when the database is updated, which works as intended, but when there are multiple items in the loop it will send a notification per each of these objects (expected, but not so intended)
My simple loop code is:
for(var idx in multiSelectSaveArr) {
calendarPage.saveCalendarMultiItem(time = multiSelectSaveArr[idx].creationDate, multiSelectSaveArr[idx])
}
The purpose of this is that time will become the unique key, whilst the value is a JSON object.
my calendarPage.saveCalendarMultiItem is a signal to my dataModel, which is where the function to store the data is, so each iteration then calls a function which handles the database writing as an individual object
The nature of my loop is that sometimes it could contain 3 objects, other times 30 - it is a different number each time.
My Question Is
Is there a way I can signal the end of the loop, meaning once the final object has been iterated through to then only send a single notification?
Thanks for any help!

You can use Array.prototype.forEach to check the index and get the array value during iteration, once the idx is at the last but one index you call you notification function to signal the iteration is over:
multiSelectSaveArr.forEach(function(val, idx){
calendarPage.saveCalendarMultiItem(time = val.creationDate, val);
if(idx === multiSelectSaveArr.length - 1) notificationCallback();
}
You can also do it using Array.prototype.entries and the for..of loop which is designed for iteration of an iterable like an array:
for(const [idx, val] of multiSelectSaveArr.entries()){
calendarPage.saveCalendarMultiItem(time = val.creationDate, val);
if(idx === multiSelectSaveArr.length - 1) notificationCallback();
}
The reason I am calling the notificationCallback() inside the loop along with the if condition is because I assume you won't send the notification if the array is empty, if I placed the callback call after the loop it would've worked regardless and also it didn't require an if, but that would still call the notificationCallback() although the loop never ran.
Do not use for..in loop to iterate over the array as it iterates over property values of an object (in this case an array object) in an unspecified order.
See this answer for more details.

Related

Implementation of a Stack using an Array, a count, and an Index

So I made a function to push user-inputted strings to a stack by using the built in .push(e) function like so:
push() {
const arrays = this.array.push(String(this.userInput))
console.log(this.array)
}
and with every click of the push button the console updates the array pushing whatever the user has inputted into an HTML text field which I have also made. I showed it to a friend and they told me that this method was sort of cheating as I'm making a Stack of stacks and that there is a way to...
Implement a Stack using only an index, a count, and an array.
Conceptually I know what these are, the index is an objects position in a given array, and an array is a collection of objects of the same variable types and a count is ostensibly a count (correct me if I'm wrong?). However tying these concepts together to implement a stack is a little beyond me as a first semester computer science student is there a lay-mans terms way of explaining how these things can be tied together to implement a stack?
To do what you're doing without using the built-in push method, just assign to the index at the current length of the array. No need to keep track of any other variables:
push() {
this.array[this.array.length] = String(this.userInput);
// if you also need your implementation to return the new length, then:
return this.array.length;
}
Or, for pop:
pop() {
const item = this.array[this.array.length - 1];
this.array.length = Math.max(this.array.length - 1, 0);
return item;
}
Keep in mind that push returns the new length of the array, so const arrays = this.array.push(String(this.userInput)) won't give you an array in return.

Array length Vs Number of values in Array

Recently i had to make an Array with values at large indexes (due to plugin constraints).
eg:
var names[100000] = "a";
var names[150000] = "b" ... and so on till 5 large indexes.
and in between all values are undefined names[100001] //undefined.
Now my doubt is Since the array has only 5 elements but if i do
names.length //it is 300001
its a large Array. I am not iterating this array nor i am running any loop through it. I will get the values directly through their defined indexes from the array.
So will this structure make any significant performance differences on the Browser or is it alright to use this as long as the number of values in the array is less irrespective of its indexes and no iteration is involved.
Thanks
The only thing that differentiates an array from a plain object is its length property and how it behaves (and a few array specific methods of course). The length value simply increases with certain operations, like setting a numeric property or pushing a new element. That's it in a nutshell. The array doesn't actually contain 100000 elements when you set the property 100000 to a value, all that's happening is that you're setting one property and the value of length is adjusted accordingly.
So, no, it won't have a lot of impact on performance, unless somebody actually iterates through the array using for (let i = 0; i < arr.length; i++).
You can create an array with the length, given by your plugin and work locally with an object to limit the iterations. After all your processing has been applied, you copy the values to the array and send it to the plugin's function.
Keep an array with the desired length as a buffer
var buffer = new Array(20000);
Internally work with an object
var data = {};
Assign values to the object
data[10001] = "foo";
Once transformations or data processing has been applied to the object, copy data to the buffer
for (key in data){
buffer[key] = data[key];
}
Send buffer to the plugin. And clear data, if desired.
By doing so, you will not iterate more, than the actual data you processed.

Use a for loop to modify and store iterations of same array

I'm trying to use a for loop to modify an array then store that modification in another array than do another modification and store that to the second array etc, but my second array is just d instances of the last iteration of my for loop. This seems like a closure problem but I can't figure out a workaround?
for (var d=1; d<arr1.length; d++) {
remove = arr1.splice(d,1).toString();
arr1.splice(d+1,0,remove);
arr2.push(arr1);
}
return arr2;
If you want to store all modified versions of your array, I suggest using an array of arrays, in this case let's call that top-level array master. Each time you modify your array, you would just push it to the master array.
This would give you what is called a "2d array". Then you would be able to access any version of your array that you wanted to. Your first array would be master[0], second would be master[1], etc. To access the first element of your second array, you can then just say master[1][0].
Hope this helps!

Trying to understand recursion within for loops in javascript

I've been staring at the answer to this question forever even writing down variables and whatnot through each iteration. I simply just don't get the process here. When I throw in console logs I see that permute is called input.length - 1 times before it ever gets to this line input.splice(i, 0, ch); It's hard to phrase the question when I am lost completely, but I guess some curiosities are: each time permute is called, it is a new instance of that function with it's own closure right? therefore variables changes that are within the function won't affect variables in other calls? does the function return permArr for each time it's called? and I suppose that doesn't necessarily affect the return of the first call? (my instinct tells me that the first time return happens, the function stops running).
Thanks for the insight.
Permutations in JavaScript?
var permArr = [],
usedChars = [];
function permute(input) {
var i, ch;
for (i = 0; i < input.length; i++) {
ch = input.splice(i, 1)[0];
usedChars.push(ch);
if (input.length == 0) {
permArr.push(usedChars.slice());
}
permute(input);
input.splice(i, 0, ch);
usedChars.pop();
}
return permArr
};
I'll give this a shot.
Overview
You start with two arrays that will have global scope: permArray will eventually hold all of the permutation arrays, and usedChars is a worker array used build each individual permutation array through all of the recursive calls. It's important to note that these are the only two variables that are accessible in the scope of every function created. All other variables have local scope to their own function call.
Then there is the recursive function which accepts an array as input and returns an array of array with all possible permutations of the input array. Now, in this particular function the recursive call is inside a loop. This is interesting because the terminating condition is actually more complicated than your basic recursive function--the recursive calls terminate when you pass in an empty input array and the for loop skips over the next recursive call.
Summary
Consider a four element array input. At a high level, the function is going to loop over the four elements of this array, pull out each element, and compute the permutation of that smaller array of three elements. With all of those three element permutations, it will append the original element pulled out to the beginning and add each of those four element arrays to permArray.
But, in order to find the permutation of the smaller three element arrays, we pull out each element, compute the permutation of that smaller array of two elements, add the element pulled out to the beginning of each of those permutations, and return each of those three element arrays up the recursion call stack so the original fourth element can be added to the beginning and counted as a permutation.
But, in order to find the permutation of the smaller two element arrays, we pull out each element, compute the permutation of that smaller array of one element, add the element pulled out the the beginning of each of those permutations, and return each of those two element arrays up the recursion call stack so the original third element can be added to the beginning of that permutation and returned up the stack.
But, in order to find the permutation of the smaller one element array, we pull out the element and compute the permutation of that empty array, which just returns, and we in turn just return our one element back up the stack so the original second element can be added to the beginning of that permutation and returned up the stack.
Details
Let's note some of the steps in this function:
var permArr = [],
usedChars = [];
function permute(input) {
var i, ch;
for (i = 0; i < input.length; i++) { // loop over all elements
ch = input.splice(i, 1)[0]; //1. pull out each element in turn
usedChars.push(ch); // push this element
if (input.length == 0) { //2. if input is empty, we pushed every element
permArr.push(usedChars.slice()); // so add it as a permutation
}
permute(input); //3. compute the permutation of the smaller array
input.splice(i, 0, ch); //4. add the original element to the beginning
// making input the same size as when we started
// but in a different order
usedChars.pop(); //5. remove the element we pushed
}
return permArr //return, but this only matters in the last call
};
Let's trace through the details using the array [4,3,2,1].
When it's first passed in, we'll take out the 4, push it to usedChars, remove it from input, and call permute on [3,2,1]. In this call, we'll push 3 to usedChars, remove it from input, and call permute on [2,1]. Then we push 2 to usedChars, remove it from input, and callpermuteon [1]. Then we push 1 tousedChars, and remove it frominput`.
This leaves us four calls deep and at step (2) with:
ch=1
input=[]
usedChars=[4,3,2,1]
At step (2), we're going to push our first permutation [4,3,2,1] to permArr. Then, moving on, since input is now empty the recursive call in (3) will simply return and in (4) we will simply add 1 back into input and remove 1 from usedChars--and this call returns.
So, at this point, we have started backing up our recursive calls and sit at step (4) with:
ch=2
input=[1]
usedChars=[4,3,2]
Step (4) will perform the critical step of the algorithm: the moving action. It takes ch=2 and adds it to the beginning of input and removes it from usedChars. This means that after step (5), we have:
ch=2
input=[2,1]
usedChars=[4,3]
Now take a look at where we are. We pushed [4,3,2,1] as a permutation, then backed up and swapped 2 and 1, and now we're going to go back into recursive calls to build [4,3,1,2] and add it as a permutation. After that we will back out some more, move around some more elements, and go back into the permutations and add them.
Getting back into it, after step (5) is executed we loop. That means we will push 1 to usedChars and make a recursive call with input=[2]. That call will push 2 into usedChars creating a the full array [4,3,1,2] and causing it to be added to permArray.
So, you're going to cycle up and down through the recursive calls building up a permutation, backing back out, rebuilding a different permutation, and backing out until you've looped over every possible combination.
I hope this helps!
The code is a bit hard to follow, because it's a mix of looping and recursion. It uses a global variable (usedChars) that is changed and restored during each call.
"each time permute is called, it is a new instance of that function
with it's own closure right? therefore variables changes that are
within the function won't affect variables in other calls?"
Well, yes and no. Each function call has its own scope, but as there are no variables that needs catching, there is no closure. The local variables i and ch and the parameter input are local to the scope, so each call has their own set of those variables. Any other variables are global, so they are shared between all calls.
The variable usedChars is changed in the code, and that change is visible to the code when the function does the recursive call, and then the variable is changed back to the previous state for the next iteration. When the function exists, the variable has the value that it had when the function was entered.
"does the function return permArr for each time it's called?"
Yes, but when the function calls itself, the return value is ignored. It's only when the array is returned from the outermost call that it is used.

getting the amount of properties in an object then getting the last one of them in a for loop

This should be very easy but I don't know how to do it.
I have this object:
var obj = eval(result);
Now I want to know how many properties contains to put it in a loop
var finalAmount = obj.length;
Now I go for the loop
for (var i in obj) {
--- some other code in here
Now here the problem I need to do something when the loop reaches the final property of the obj, so this is what Ive tried:
if (i+1 == finalamount){
//do something
} else {
//do something else
}
so basically using the i as a pointer to compare it to the var that contains how many items there are and when finding the final one of the loop then do something...
In this case i is not necessarily numeric, and so i+1 may not give you the desired results. You should set up a separate counter variable that you increment at the end of each loop iteration.
In your case obj must be an Array. If it is not, i+1 throws error.
The for-in loop does not ensure any sequence order, even it is an Array, it is only used to iterate unordered properties. You need traditional for(index=0;index<length;index++) (if it is an Array)
If your obj variable is an Object instead of Array, you can't get "last property" only with object data structure, it must provide more information (property order).

Categories

Resources