I have this loop right here:
function sendBackOne() {
var selected = paper.project.selectedItems;
for (var i = 0; i < selected.length; i++) {
console.log(selected[i].name);
}
where selected is an array with items that i iterate over.
One of the items has a ''name'' property set to ''something''. I don't want to go over that element in my loop,i need to disregard it.
How would i go about doing that?
The best way i can figure is writing an IF/ELSE statement in the loop to check the name and if it's not ''something'' i do what i need to do.
Is this the best way?
Simple:
if (selected[i].name == "something")
continue;
Use continue to head to the next iteration.
Yes it is. You can also use a continue statement like this
var selected = paper.project.selectedItems;
for (var i = 0; i < selected.length; i++) {
if (selected[i].name === "something") continue;
... // Whatever you wanted to do, goes here
}
Related
I wonder if someone can clarify something for me. I have a bit of code to check an array for overlapping values depending on different values. Basically its the contents of a google sheet in rows and comumns for this is specifically GAS. What I have at the moment is
var e = [[2,4,3,4,2],[1,5,3,6,2],[2,4,3,4,1],[1,4,3,6,1],[2,4,3,6,5]];
var i; //id of entry to check
var j; //id of element to check
var k; //id of entry to compare
for (i in e){ //2D ARRAY ARRAY
for (k in e){ //ELEMENT TO COMPARE
if (e[i][2] === e[k][2] && e[i][3] === e[k][3] && e[i][0] && e[i][0] >= e[k][0] && e[i][1] <= e[k][1] && e[i][4] <= e[k][4] && i !=k){
e.splice(i,1);
continue;
}
}
}
return e;
I had to add the continue; as otherwise if the last array checked was also marked for splice the code failed. But I assumed break would also work in place of continue but for some reason it does not. I thought break would return to the outside loop but does it permanently break that bit of code?
Thanks people
EDIT: spoke too soon. code still fails even with continue. head scratching continues
continue jumps directly to the next iteration, so:
while(true) {
console.log("a");
continue;
console.log("b");
}
will only log a as it will jump back to the beginnig of the loop if it reaches continue.If you however move continue to the last line of the loop (just as in your code) it does nothing as it would jump to the begining to the loop one line later, so it just skips an empty line.
I thought break would return to the outside loop
Yup, thats what happens and that is actually a good thing as if you removed the element already, it won't make sense to check for other dupes as you don't want to remove it twice.
Now the real problem is that splice changes the indexes, so if you splice out the fourth element, the fith element becomes the fourth element, but the loop continues to the fith element without checking the fourth element again (which is now a different one). Therefore you have to go back by one element before you break:
for(let i = 0; i < e.length; i++) {
for(let k = 0; k < e.length; k++) {
if(i === k) continue; // < good usecase
if(/* equality checks */) {
e.splice(i, 1); // remove the element
i--; // go back by one as we changed the order
break; // exit the inner loop
}
}
}
IMO:
1) I would favor for(const [i, value] of arr.entries() over for..in
2) you will forget what arr[i][2] is very soon, giving proper names to the indexes makes it way more readable:
const [idA, someValueA] = e[i];
const [idB, someValueB] = e[k];
if(idA === idB && someValueA <= someValueB // ...
3) e is a bad name.
You can use a labelled break to break out of nested loops.
eg
var num = 0;
outermost:
for(var i = 0; i < 10; i++){
for(var j = 0; j < 10 ; j++){
if(i == 5 && j == 5){
break outermost;
}
num++;
}
}
I have a for loop that suddenly stops working when I try to push to an array. The best way to describe what's going on is just to show my code and try an explain what's going on.
for (var i = 0; i < childs.length; i++) {
if (childs[i].length > 0) {
for (var j = 0; j < amountsValue[i].options.custValues.length; j++) {
var label = amountsValue[i].options.custValues[j].label;
var value = amountsValue[i].options.custValues[j].value;
for (var k = childs[i].length - 1; k >= 0; k--) {
if (childs[i][k].attributes[label] != value) {
childBackup.push(childs[i][k]);
childs[i].splice(k, 1);
}
}
}
amountsValue[i].id = childs[i][0].attributes.internalid;
childs.push(childBackup);
}
}
What's happening is I am looping through an array of items which may or may not have custom options available such as different sizes or colours. The loop will check to see if there are any then get the value and label from the array.
After this, we then loop again to try and match up the values with option values stored within a separate model. The plan is to check if the value is the same as the one stored and if not then splice it from the array. The process of elimination should eventually leave only one option left and that will be used to get the internalid.
During this a back up of the spliced objects is kept so that they can be appended to the array again so that the user can change the option they want. The problem is using childs.push(childBackup) stops the browser form reading the options on amountsValue. This works if the code is removed or it is pushed into another index so I'm really not sure why it isn't working.
Does anyone have any suggestions on how to get this working? I'm sorry if this doesn't make much sense, I've tried to explain it as best I can but let me know if anything needs to be cleared up.
EDIT: I have fixed the issue. Thank you to everyone who suggested ways to solve the problem. As others said, I was trying to manipulate the array I was looping through and changing the length on it. So that part of the code was taken outside the loop and after the initial loop another loop was set up which contained the following code:
for (var i = 0; i < childBackup.length; i++) {
childs[0].push(childBackup[i]);
}
It now works as intended. Thank you.
You are manipulating the array you are looping through.
var count = childs.length;
for (var i = 0; i < count; i++) {
if (childs[i].length > 0) {
for (var j = 0; j < amountsValue[i].options.custValues.length; j++) {
var label = amountsValue[i].options.custValues[j].label;
var value = amountsValue[i].options.custValues[j].value;
for (var k = childs[i].length - 1; k >= 0; k--) {
if (childs[i][k].attributes[label] != value) {
childBackup.push(childs[i][k]);
childs[i].splice(k, 1);
}
}
}
amountsValue[i].id = childs[i][0].attributes.internalid;
childs.push(childBackup);
}
}
I have an array items. I need to make sure that in the current iteration of the loop I can safely call the next item of the array
for(var i = 0; i < items.length; ++i) {
// do some stuff with current index e.g....
item = items[i];
// then do something with item # i+1
if(items[i+1]) {
//do stuff
}
}
Is this how it is done or if not how/what would be the better way?
P.S. I do not want to do a bound check
If you want to loop through every element except the last one (which doesn't have an element after it), you should do as suggested:
for(var i = 0; i < items.length-1; ++i) {
// items[i+1] will always exist inside this loop
}
If, however, you want to loop through every element -even the last one-, and just add a condition if there is an element after, just move that same condition inside your loop:
for(var i = 0; i < items.length; ++i) {
// do stuff on every element
if(i < items.length-1){
// items[i+1] will always exist inside this condition
}
}
if(items[i+1]) will return false (and not execute the condition) if the next element contains a falsey value like false, 0, "" (an empty String returns false).
Put a value check on variable i and make sure it is less than items.length-1 in order to safely access items[i+1].
for(var i = 0; i < items.length-1; ++i) {
if(items[i+1]) {
//do stuff
}
}
Drop the for loop and use array#forEach, and simply check whether a next value exists:
items.forEach(function (item, index) {
if (!items[index + 1]) return;
// do something with item and items[index + 1]
});
Why is the "localStorage.removeItem" stopping the loop? If I remove "localStorage.removeItem" and only leave the "alert", it loops though whole thing, but with "localStorage.removeItem" it stops on the first match.
function removeTask() {
for (i=0; i < localStorage.length; i++){
checkbox = document.getElementById('utford'+i);
if (checkbox.checked == true) {
alert(i);
localStorage.removeItem(localStorage.key(i));
}
}
printList();
}
If you remove an item, the keys move down an index. You need to loop backwards.
function removeTask() {
for (var i=localStorage.length-1; i>=0; i--){
var checkbox = document.getElementById('utford'+i);
if (checkbox.checked == true) {
localStorage.removeItem(localStorage.key(i));
}
}
printList();
}
You are iterating on an array-like object while deleting its entries.
This cannot work as the entries order will be mixed up on each deletion.
Consider this example.
First iteration deletes entry #1:
Entry key value
#1 my-first-key my-first-value
#2 my-2nd-key my-2nd-value
Second iteration tries to delete entry #2:
Entry key value
#1 my-2nd-key my-2nd-value
??? ??? ???
From what I make of your code, I'd advise you to use string keys instead. You could then pick the same key name as your elements' IDs.
I am attempting to catch the last case in a forEach loop, but all cases seem to evaluate to false instead of the last one being true. My code:
for(var i in networks){
if (i == (networks.length - 1)){
//do stuff
}
}
What is going wrong?
Try this:
for(var i = 0, j = networks.length; i < j; i++){
if (i == (j - 1)){
//do stuff
}
}
I personally despise the for...in loop in JavaScript because it brings into the picture a whole bunch of unwanted properties, it's unreliable - needs a ton of sanity checks to make sure the current property is not of an unwanted type or undefined. I can go on and on about this. I suggest that the only time that you ever think of using it is when you are iterating over objects and you need key values.
If networks is an array of numbers in order from 0 to n, that should work. ;) If it's not, you might want to consider a standard for loop:
for(var i = 0; i < networks.length; i++) {
var network = networks[i]; // in case you need this.
if (i == (networks.length - 1)){
//do stuff
}
}