if(childrens are present) {
while(childrens.length ! ==0) {
do something
}
}
// Execute this function fnName()
My problem here is the while condition is getting executed, but when the length becomes zero... it does not come out... and execute the fnName()
If you're actually removing children from the array in the loop, that should be fine other than that you've got the spacing wrong on the operator; it should be !==, not ! ==:
while(childrens.length !== 0) {
Note that to actually remove children from the array, you have to use one of the array mutator methods, like pop or splice. My guess is that you're not doing that.
The more normal thing to do would be to loop through the array without mutating it:
var index, len, child;
for (index = 0, len = childrens.length; index < len; ++index) {
child = childrens[index];
// Use `child` for each child
}
Or using the new ES5 stuff like forEach (which requires knowing your users will have a very up-to-date browser, or including an "ES5 shim" since forEach is one of the things that can be shimmed):
childrens.forEach(function(child) {
// Use `child` for each child
});
Side note: The word "children" is already a plural (the singular is "child"), so there's no "s" on the end of it. Just one of English's irregular plurals (there are several).
The usual strategy is to create childrens as an array or similar object that has a consistent property that is checked on entering the loop, which continues while the condition is true.
In this case, it would be best to create childrens as an array, then decrement it in the loop so:
while (childrens.length) {
// do stuff to reduce the length of childrens
}
So when childrens.length is zero, the test is false and the loop exits (or if childrens.length is zero to start with, is never entered).
For checking not equal to zero it should be
children.length != 0 // (you have written in the question children.length ! ==0)
If this is a typo the other problem might be you are not decrementing children in the while loop. Hence, it goes to an infinite loop.
Related
str.indexOf(searchValue[, fromIndex])
The index of the first occurrence of searchValue, or -1 if not found.
- MDN web docs
Why was -1 chosen to be the returned value by .indexOf if it doesn't find a match in the array?
console.log([].indexOf()) // -> -1
Would it not be more suitable to have 0 instead? It would make sense because there are indeed 0 matching element. And this way we could have used it directly in a conditional statement, for example:
if( Array.indexOf(String) ) { ... }
Instead of
if( Array.indexOf(String) !== -1 ) { ... }
Why is that? Any particular reason? I've seen the same in Java, C++ and C. Is this because of how the native function was designed?
Would it not be more suitable to have 0 instead?
No. Indexes start from zero.
var str = "ABC";
console.log(str[0]);
console.log(str.indexOf("A"));
(The same is true of arrays, which you used for your examples despite quoting the documentation for strings).
Well. It's pretty straight forward as to why. indexOf returns the position of an element not if it exists or not. Plus all ( 99% ) programming languages are 0 indexed, or better say strings and arrays are 0 indexed which means that the first element is at position 0.
Think of position as the offset of an element from the start of the array. So the distance/offset of the first element from the start of the array is, well, 0 :)
Maybe you are looking for includes() which checks if an element is inside an array.
const arr=[1,2,3]
// classic
if (!arr.includes(4)) {
console.log('4 does not exist (classic)')
}
// or short circuit
!arr.includes(4) && console.log('4 does not exist (short circuit)')
// conditional (ternary) operator
!arr.includes(4) ? console.log('4 does not exist (ternary)') : ""
Observation
Also you shouldn't use indexOf() as a boolean condition because for example
let arr=['a','b','c']
arr.indexOf('a') ? console.log('true') : console.log('false')
In the above example, indexOf(a) returns it's position 0. In a boolean condition 0 is treated as false by javaScript. So it would not give you the expected result.
Everyone else is saying the same thing, but let me try another wording of the answer.
In Javascript arrays are indexed starting with element 0. So if the string qas found at the begining the valid return value would be 0. If string not found was reported as 0 you would not know if it was not found or found at the beginning. -1 is never a valid value for a position in a string.
As to your test
if( Array.indexOf(String) ) { ... }
you could instead use
if( 1+Array.indexOf(String) ) { ... }
to avoid using the !== -1 test.
As a general consideration, the result of Array.indesOf() is overloaded. The result contains both the funciton result and an error code. This overloading allows the function call to be used directly in a test. Consider, however, that if the function call is in the if statement you probably will need to call the function again, which is an efficiency loss. If before the if you made an assignment of the result and then tested the result you would be computationally more efficient. There is not even a memory cost because variables in funtions are on the stack which is cleared on function return if you keep the variable local.
A function that returned a structure containing a success/fail flag and a result is a clean way to do such a thing that generalizes function calls that may fail, and is a convenient place to put exception handling without complicating the simple test you want to do.
Because in almost every programming language, 0 is the first position of an array.
indexOf() gives you the position of the element in the array and valid index of array starts from 0, 1, ... and so on till the array.length-1 so if the indexOf() would return 0 for non existence element then that would be incorrect as 0 is a valid index. Thus -1 is used.
So I have a fairly good amount of experience in coding. I've dabbled in Basic, HTML, Javascript, C, and C++, though the ones I've been using most recently are HTML and Javascript.
I am incredibly familiar with the for-loop. I've used it many times to loop through arrays, to operate recursive functions, etc. I know what it does and how to use it, but my question is about how it works.
Premise
In most languages, the basic syntax of a for loop is such:
var upperLimit = 10;
for(var i = 0; i < upperLimit; i++) {
/*Code to be executed*/
console.log(i);
}
In Javascript, this will output the numbers from 0 to 9 in the console.
I know that the parentheses contains 3 parts, each separated by semicolons.
The first is the initialization, which typically sets up the variables to be used to loop the statements.
The second is the condition, which runs before any of the code between the curly braces is executed. If it results in a True, the code is executed. Otherwise, the for-loop stops.
The third is the increment, which contains the last bit of code to be executed in the loop, and, by extension, the last thing executed before the next condition check.
Question
So, again, my question is how strict are these definitions?
The initialization's definition doesn't allow for much. It just says that that line is executed once, it's executed before anything else in the loop, and it's scope is limited to the loop. I can't think of much else you'd want to put in that position other than an iterative variable.
But what about the other two? I've seen codes where the condition is simply a variable, and as long as it's positive (since positive numbers taken as a boolean just covert to true), the loop continues.
Then there's the increment, which seems to be the loosest of these parts. Is it really just the last thing to be executed in a code, or does it explicitly need to iterate the variable declared in the initialization? It seems to be the former for the languages I'm familiar with.
For example, I decided to make a non-standard for-loop, and I came up with this routine:
var numbers = [0,1,2,3,4,5,6,7,8,9];
for(var i = 0;
numbers.length;
console.log(numbers.pop())) {}
It runs exactly as I expected: It outputs each member of the numbers array in the console in descending order, leaving an empty numbers array afterwards, and it's done using what is basically an empty for-loop.
Ending
So are my assumptions correct? If so, are there any practical applications for using a for-loop in a format apart from the one I wrote at the top of this question (possibly closer to he second format)?
Before all, you give a array
var numbers = [0,1,2,3,4,5,6,7,8,9];
The codes below is a correct for loop.
for(var i = 0;
numbers.length;
console.log(numbers.pop())) {}
Javascript defined for like this
for ([initialization]; [condition]; [final-expression])
statement
For you code initialization is 'var i = 0', and execute once at start of loop.
The condition is 'numbers.length', and value is 10. When a number not 0, Javascript will convert it to boolean true. So condition is true.
The final-expression is 'console.log(numbers.pop())'. When execute 'numbers.pop()', numbers.length change to 9. But it still is true.
At second time, condition will return true again. The final-expression is execute too.
Until numbers.length become 0, Javascript convert it to boolean false. The loop will end.
The scope of the initialized variable is not limited to the loop, it's valid for the whole function (undefined before that line). You can initialize multiple variables using a comma. for (var i=0, j=1; i < 10; i++)
The second part, anything that evaluates to a truthy value will cause the loop to keep going:
Truthy: 1, -1, true, "something", {a: 2}
Falsey: 0, false, null, undefined
You could omit this and rely on a break in your code
The third part just lets you update the looping variable, you could omit it and do it within the for loop body.
Here's an answer that provides a nice way to loop that is non-standard, and comes with caveats, please see the link.
var list = [{a:1,b:2}, {a:3,b:5}, {a:8,b:2}, {a:4,b:1}, {a:0,b:8}];
for (var i=0, item; item = list[i]; i++) {
// Look no need to do list[i] in the body of the loop
console.log("Looping: index ", i, "item" + item);
}
In most languages, the basic syntax of a for loop is such:
for(initialization; condition; iteration) {
/*Code to be executed*/
}
Both three are usual expressions and you can use any valid expressions here:
for(
var i=arr.length, othercond=true;
i;
othercond?i--:i++, console.log(i),updateothercond()
);
Have been playing around with the FizzBuzz problem, and I am wondering why the following code won't execute, nothing gets printed to the console.
var i = 0;
while (i = 0, i < 100, i++ ) {
if ( i % 3 === 0) {
console.log("Fizz");
} else if ( i % 5 === 0) {
console.log("Buzz");
} else {
console.log(i);
}
}
What am I missing?
You used the wrong looping construct. It should be a for, not while. Also note that it's semicolons between the clauses, not commas:
for (i=0; i < 100; i++) {
What you have is this:
while (i = 0, i < 100, i++) {
The comma just evaluates the left side, throws the result away, and then evaluates the right side. So that sets i to 0 (and discards the zero value returned by the assignment), tests that i is less than 100 (but does nothing with the true value returned by the comparison), and uses the value of the last expression (i++) as the loop condition for the while. Since i is 0, which is falsy, the loop body never executes.
Note that if you had used ++i instead, it would make no difference in the for case, but your while version would loop forever instead of not running at all, since i would already have been incremented to 1 the first time it was tested for truthiness.
I believe you are simply confusing the way you make 'for' and 'while' loops. You've built your 'while' like you would a 'for'!
Think of it this way: when you write a while loop like this:
while(i<100) {
You're saying, while (this condition is true). All that you need between the parentheses is a statement to determine whether it's true or not. Somewhere in the loop, you (usually) would need to change the value of i, or you'd (probably) get an infinite loop.
Now, the for loop, we'll need more information between the parenthesis... we'll need all the information that determines the amount of loops we'll take. Just like you've written it there, we're writing for (when my variable equals this; Loop until this condition is true; change the variable like this).
Generally, this means that 'while' provides more flexibility in how you determine the logic of your loop, but a 'for' loop is probably the easiest to read.
I am trying to create a function that will trim off array values that are not 4 chars long. For some reason, it does not work. I think that it might be with the return statement but I am not sure and I need help with it. Here is the code for the function: (Please don't suggest ways of making the hasher better, I just need help on the function)
function cutit(seq){
for(var i=0;i<seq.length;i++){
var temparr=seq[i].split("");
if(temparr.length % 4 !== 0){
seq.splice(seq[i],1);
return seq;
}
}
}
Five things:
Yes, the return should happen after the loop not after the first found item to delete.
.splice() takes an index for the first parameter, not the element. Pass i instead of seq[i].
splice(…, 1) does decrease the length of the array you're iterating over by one. You need to take care of that and decrease your counter as well to have a look at the i index again, where on the next iteration the next element will sit.
Instead of splitting the string into an array of single chars and taking the length of that, just take the length of the string directly.
Your functions removes all strings that are not a multiple of 4 long, not all that are not exactly 4 characters long. Not sure whether that is intended.
function cutit(seq) {
for (var i=0; i<seq.length; i++) {
if (seq[i].length !== 4) {
seq.splice(i--, 1);
}
}
return seq;
}
Also, notice that mutating an array is seldom a good idea (especially in an inefficient way like this with multiple splices). Returning a new array is so much easier, and you can use the higher-order filter Array method for that:
function cutit(seq) {
return seq.filter(function(str) {
return str.length === 4;
});
}
I am trying to make a small program that prompts a user to add items to a grocery list.
I read about using recursion to loop. I understand a while loop would probably be better suited for this task, but I ran into the same problems with the while loop and I wanted to try recursion. It just sounds like I know what I'm doing... "Yeh, I used recursion to enumerate the array while prompting validation from the user... hur hur hur"... but, I digress.
Here is the code:
function addToArray() {
var array = [];
array.push(prompt("Add items to array or 'q' to stop"));
if (array.pop() == 'q') {
document.write(array)
}
else {
addToArray();
}
}
addToArray();
If you'll notice, it loops like its supposed to but it is not adding items to an array. I have tried the array[i] = i technique as well but to no avail, the array remains empty. Also, why is it that by using a function with no args am I not running into too much recursion? Is it because of the conditional statement?
If you know what I'm doing wrong, try and hint towards the right answer rather than just blurting it out. I'd like to have that 'Aha' moment. I think this all helps us learn a bit better.
Thanks guys. (and gals)
You're creating a new array instead of passing it to the recursive call.
Do this instead.
DEMO: http://jsfiddle.net/kDtZn/
function addToArray(array) {
array.push(prompt("Add items to array or 'q' to stop"));
if (array[array.length-1] == 'q') {
array.pop();
document.write(array)
}
else {
addToArray(array);
}
}
addToArray([]);
Now you start with an empty array, and for each recursive call, it passes the same array forward.
Also, I changed it so that it doesn't use .pop() in the if() condition, otherwise you'll always end up with an empty array when it comes time to write it. (The .pop() method actually removes the last item.)
Finally, make sure you're not using document.write after the DOM is loaded. If so, you need to change it to use DOM manipulation methods instead.
You could take a different approach so that you don't need .pop() at all.
DEMO: http://jsfiddle.net/kDtZn/1/
function addToArray(array) {
var item = prompt("Add items to array or 'q' to stop");
if (item == 'q') {
document.body.textContent = array;
} else {
array.push(item);
addToArray(array);
}
}
addToArray([]);
The reason your while loop didn't work is very likely because of the original .pop() issue.
Your function recreates var array = [] on every loop/recursion. I am not sure if recursion is the right tool for the job in your case - it does not seems like it - but if you're starting out with JavaScript/development and just trying it out then you're fine.
While an 'infinite loop' is probably what you really want (as it would probably make the code simpler), you can do this with recursion by defaulting the array and passing it as an argument to the function. Like so...
function addToArray( array ) {
var array = array || [];
array.push(prompt( "Add items to array or 'q' to stop" ));
if ( array[array.length - 1] === 'q' ) {
document.write(array.slice( 0, -1 ))
} else {
addToArray( array );
}
}
addToArray();
There's two issues with the code as you presented. One, as pointed out earlier, you're redefining your array variable every time you call your function. Second, array.pop() alters your array, so when you get to the document.write call, you'd be printing an empty array anyways.