I know how to skip first iteration in javascript foreach loop
dataObject.slice(1).forEach((row) => {});
I want to know how to do the same thing using for of loop in javascript, please help me, thanks
for( const row of dataObject )
The same way you're skipping it with forEach - replace the dataObject expression with dataObject.slice(1).
for( const row of dataObject.slice(1) )
While CertainPerformace's solution is what most people, including me, would go with, it does have a the downside of having to make a temporary array copy, which would be bad when you have huge arrays (but completely unnoticeable usually).
To prevent copying the array, create a temporary variable to check if it's the first in the loop. The downsides of this is the temporary variable, and the if check on every iteration could make it slower.
let first = true;
for (const row of dataObject) {
if (first) {
first = false;
continue;
}
// ... rest of script
}
And I would probably just use a traditional incremental for-loop anyways if you want more control over iteration, since forEach, for-of, and for-in are meant to iterate over everything.
Related
Backset is an array of arrays, I am trying to filter out any arrays which contain a repetition of elements, such as an array with 2 ones. I would like to remove these from the Backset array.
However this is not happening and some arrays in backSet such as [1,2,2] stay in backSet.
for(z=0; z<backSet.length; z++){
backSet[z].sort();
tempBackSort = [];
for(k=0; k< backSet[count].length; k++){
if(tempBackSort.includes(backSet[count][k])){
backSet.splice(backSet.indexOf(backSet[count]),1);
kon = 0;
continue;
} else{
tempBackSort.push(backSet[count][k]);
kon = 1;
}
}
if(kon===1){
count++;
}
backSet[z].sort();
}
There are several issues:
Where you have continue now it accomplishes nothing. You need break, so the inner loop is exited
You try to overcome the problem of iterating over an array where elements are sometimes removed by using count, but:
count is not initialised
You still have code that works with backSet[z] instead of backSet[count]
It would have been easier to just decrease z when an element is removed, or even better: to let the outer loop iterate backwards from end to start -- then you don't need to adjust any index.
Variables are implicitly declared as globals: this is bad practice. Define your variables with let or const.
By sorting the inner arrays, you mutate the original data. This might be OK for your case, but still it is maybe surprising for code that depends on this piece of code.
Sorting is also not the most efficient way to find duplicates. Instead of pushing values in tempBackSort, put them in a Set (which cannot contain duplicates) and compare its size with the original array: if their sizes are not the same, then there are duplicates.
Instead of splicing inside a loop (which is the cause of your trouble), use the array method filter which returns the filtered array.
Here is how it could be coded:
backSet = backSet.filter(arr => (new Set(arr)).size == arr.length);
I wrote this solution to a problem I had, but I don't feel entirely comfortable with it. It seems to be dangerous, or at least in bad practice to use an array to redefine itself, sort of like trying to define a word but using the word in the definition. Can anyone explain either why this is wrong, or why it's ok?
let array = []
// other stuff happens to fill the array
array = array.filter(element => element !== true)
The reason I'm doing it this way is that I need that same variable name (array, for these purposes) to remain consistent throughout the function. The contents of the array might be added or removed multiple times before the array gets returned, depending on other behavior happening around it.
Let me know if this is too vague, I'll try to clarify. Thanks!
It's perfectly fine. The right side (array.filter(element => element !== true)) of the assignment will be evaluated first, generate a completely new array and only then it'll be assigned back into array.
You can loop through your array backwards and remove the items, as to not allocate another array and reassign.
for (i = array.length - 1; i >= 0; --i) {
if (!!array[i]) {
array.splice(i, 1);
}
}
This solution is:
Fast
Memory efficient
Will not interfere with any other code that has a reference to your original array.
When I'm working with data, I normally have the need of create Arrays or Objects on a loop, let's say "on the fly".
Lets say for example I want to rearrange an array grouping the element by one of the array keys: One of the methods I use is to loop trough an for in. But the problem is when I define more than one index on the fly.
for(key in array){
newArray[array[key]['gouping_key']] = array[key];
}
This example works fine. But if you have more than one element with the same grouping_key, this code is going to override your previous element.
So, I try this:
var i = 0;
for(key in array){
newArray[array[key]['gouping_key']][i] = array[key];
i++
}
But when I add that second index the interpreter complains saying that the newArray[array[key]['gouping_key']] is undefined. Problem it doesn´t seems to have on the previous example.
Why is that?
I've made this fiddle with an example in case the previous snippets an explanation would be insuficient and unclear. In the fiddle you have three snippets (two commented out).
The first one is the error I get when trying something like what Iǘe mentioned previously.
The second is the solution I use.
And the third an example of the creation of an array on the fly with only one index.
Summing up, I want to know why, when you add the second index, you get that error.
Thanks!
var i = 0;
for(key in array){
// If nested object doesn't exist, make an empty one.
newArray[array[key]['gouping_key']][i] =
newArray[array[key]['gouping_key']][i] || [];
newArray[array[key]['gouping_key']][i] = array[key];
i++
}
You need to create an array to push to, it's not created for you. You can use the || operator to only create an empty array if it's undefined.
Also, that's a lot of nesting to follow... If I may...
var x, y;
y = 0;
for(key in array){
x = array[key].gouping_key;
newArray[x][y] = newArray[x][y] || []
newArray[x][y] = array[key];
y++
}
See how much more readable that is? It's also faster! You dont have to deeply traverse complex objects over and over again.
First using for in for arrays is no good idea, it does not what you are expecting I think. see: https://stackoverflow.com/a/4261096/1924298. Using a simple for loop (or while) should solve your problem.
I want to remove an item from an array, is array.splice(x,1) the best way to go?
Is array.splice(x,1) functionally equivalent to delete array[x]; array.length-=1 ?
I've read these threads: Javascript object with array, deleting does it actually remove the item? and Deleting array elements in JavaScript - delete vs splice
and did some tests:
<script>
var arr=[];
for(var x=0;x<100000;++x){
arr.push(x);
}
var a=new Date().getTime();
for(var x=0;x<50000;++x){
arr.splice(49999,1);
}
var b=new Date().getTime();
alert(b-a);
</script>
<script>
var arr=[];
for(var x=0;x<100000;++x){
arr.push(x);
}
var a=new Date().getTime();
for(var x=0;x<50000;++x){
delete arr[49999];
arr.length-=1;
}
var b=new Date().getTime();
alert(b-a);
</script>
The timing difference is over a magnitude of 100, making the itch to use the second solution almost irresistable.. but before using it, I would like to ask this question: are there any traps i should look out for when i use delete array[x]; array.length-=1 instead of array.splice(x,1)?
If you're just lopping off the last element in the array, you can use pop() and throw away the result or just decrement the length by 1. The delete operator isn't even required here, and splice() is more appropriate for other uses.
Specifically, section 15.4 of the ECMAScript specification says:
whenever the length property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted.
Both methods mentioned are outlined at MDC:
Array pop()
Array length
Either are appropriate for your situation - by all means modify length if you get better performance from it.
array.splice may perform other internal operations relevant to the splice.
Your delete array[x]; array.length-=1 just hacks around the public interface and assumes that there's nothing else to do internally.
In fact, this is the cause of the timing difference: there is plenty more to do internally in order to actually splice the array.
Use the proper interface. That's why it's there.
Using delete does not delete the element. After delete somearr[n] somearr[n] still exists but its value is undefined. There are a few ways to remove elements from arrays.
within an array for one ore more elements: Array.splice
from the end of an array (i.e. the last element): Array.pop() or maybe Array.length = Array.length-1
from the beginning of an array (i.e. the first element): Array.shift() or Array.slice(1)
To be complete, using Array.slice you could make up a function too:
function deleteElementsFromArray(arr,pos,n){
return arr.slice(0,pos).concat(arr.slice(pos+n));
}
Deleting array elements just sets them to undefined - that's why it is so fast. It does not remove the element. Decreasing the length of the array makes it even worse as the array length doesn't change at all!
In other words: the response to your question title is no and you should use splice() to achieve the intended effect. You can use the delete 'trick' to achieve greater performance only if your code handles the possibility of undefined elements. That can be useful, but it has nothing to do with 'removing an item from an array'.
phew! That was a long title.
I'm reading WROX' book on Professional JavaScript for web developers and I came across this sample code, and I was just wondering if that was best practice:
function convertToArray(nodes) {
array = new Array();
for (var i=0, len=nodes.length; i < len; i++) {
array.push(nodes[i]);
}
return array;
}
The thing that's got me scratching my head is the "len=nodes.length". Am I wrong in thinking that the first sentence in a for-loop is only run once? Is there a reason you'd want to set a variable (len) to the length of the nodeList before running through it? Would you do that to a normal array as well?
Thanks
That is for performance reasons. A local variable is faster for several reasons:
The the length will need to be accessed all the time in the loop, once per every iteration;
A local variable lookup is faster than member lookup;
If nodes is an array, then .length is a magic property that may take a bit longer to retrieve than a member variable.
If nodes is an ActiveX object, then .length might result in a method call into the object, so that's the most expensive operation of all.
While we're discussing micro-optimizations, the following should be even faster:
function convertToArray(nodes) {
var i = nodes.length,
array = new Array(i); // potentially faster than `array = []`
// -- see comments
while(i--)
array[i] = nodes[i];
return array;
}
It needs one less local variable, uses a while and not a for loop and uses array assignment instead of the function call push().
Also, because we're counting down we pre-allocate the array's slots, the array's length doesn't have to be changed each iteration step, but only on the first one.