never seen for loop this way how does this work? - javascript

I am just reading through a book but it didn't mention using for this way. The most common way I can understand but this I have no idea how it start and end.
this is a function which has a for loop in it and what's being inserted into the argument is an object which inherits objects and objects like a list.
function listToArray(list) {
var array = [];
for (var node = list; node; node = node.rest)
array.push(node.value);
return array;
}
var object = {
value: 10,
rest: {
value: 20,
rest: {
value: 30,
rest: null
}
}
}
console.log(listToArray(object));
// → [10, 20, 30]
for (var node = list; node; node = node.rest) this is the part where I don't understand how it works. How it start or end.
I just have a simple guess myself to start off, node is an object so if node != null then node = list and node = node.rest which is the next object

A for loop take three arguments:
for ([initialization]; [condition]; [final-expression])
var node = list; runs when the loop is started.
node is the condition, if it is false, the loop won't go around again.
node = node.rest is run at the end of the loop.
So:
It sets node to list and then keeps replacing node with the value of the previous nodes rest property.
Eventually node is { value: 30, rest: null }, so it sets node to null then tests if null is true and then stops because it isn't.

Like in any other c based language, for loop is basically formed this way: for(initialization;condition;incrementation)
In this code, the initialization part is defining a new var named node, and initializing it´s value to the same as the argument list.
The condition part node in javascript means, while node != null (or unassigned)
The incrementation part is setting node to the value of node.rest.
I dunno what node.rest does, but I suppose it will move to the next node in the tree/graph.
So in this case, the for starts when list is assigned, and ends when node.rest returns null/unassigned.

This is actually, really interesting! But what you have here is a for loop used in a pretty creative way to iterate deeper into an object.
for (var node = list; node; node = node.rest)
If we think about for loops in a traditional sense, something like
for (var i = 0; i < 10; i++)
We can draw a few parallels.
If you look at the MDN for a for loop, you see that it's broken up into three sections:
for ([initialization]; [condition]; [final-expression])
Initialization -- Specify variables, etc that will be used at the start of the loop, in this case our starting node is equal to the list passed in.
Condition -- Now here's something a little different, but basically this middle statement is condition to determine if the loop should execute. Most of the time you see i < 10 or some numeric comparison because that's a common use case. This example is leveraging the truthiness of objects in javascript. That is, an object, taken by itself evaluates to true.
ex. if({}) // will be true The fact that node is placed there by itself is basically saying "Look at the truthiness of node, if the object exists, then let's run the loop! Otherwise node will be undefined, and undefined is a falsey value in javascript.
Lastly we have the final expression, or what I like to call the 'update' section. We're essentially assigning node to be equal to its child property, which means we're iteratively going deeper and deeper into these objects. if node.rest exists, then the next iteration of the loop will start there and run itself again if node.rest actually existed in the previous loop.
Good question. I enjoyed that one.

Try this :
Boolean(object.rest); //true
Boolean(object.rest.rest); //true
Boolean(object.rest.rest.rest); //false

Related

Reversed Linked List - Javascript - Using Class or just define a function? and how to calculate Time/Space Complexity

I understand that there are a few reverse linked list questions using javascript, but I was hoping for more clarity on a solution that someone else had provided.
Is the use of a class LinkedList necessary to declare a linkedlist or would just doing it like this example given work?
I'm just not clear as to how this function is just declaring a variable called reverseLinkedList and solving it as opposed to actually using the class.
Not sure if that made any sense, but otherwise, would this solution be clear enough to solve the reversing a linked list problem?
Also, would this be considered a O(n) for time complexity? As it has a while loop that is set for a finite amount of time to run. And i'm not sure about space complexity.
// reverse a linked list
const reverseLinkedList = (linkedlist) => {
let node = linkedlist;
let previous = null;
while(node) {
// save next or you lose it!!!
let save = node.next;
// reverse pointer
node.next = previous;
// increment previous to current node
previous = node;
// increment node to next node or null at end of list
node = save;
}
return previous; // Change the list head !!!
}
linkedlist = reverseLinkedList(linkedlist);
There are a couple things going on here
First this declaration
let reverseLinkedList = function(linkedlist) {
is similar to this declaration
function reverseLinkedList(linkedList) {
except that you can't call reverseLinkList until it's been declared in the first example. You can read more about hoisting here
var functionName = function() {} vs function functionName() {}
Second using a class or function doesn't really matter all that much. You will see that classes in Javascript are really just syntactic sugar (but there are some gotcha's you can read about here)
are es6 classes just syntactic sugar for the prototypal pattern in javascript?
Lastly the time complexity of this function is O(n) because it just loops through the list once.
Hope that helps!
Either way is fine. Making a class LinkedList would allow you to add methods to it, but it's overkill for solving a single reverse linked list problem.
A linked list is just a collection of nodes, where each node references the next one with a next object property.
If you wanted to add a bunch of convenience methods to the LinkedList, then yeah, a class would be useful. But for a single problem like list reversal, the solution you posted assumes that the function takes as input the first node in the list and that each node (just a JavaScript object) has a next property.
For example, say I was solving multiple linked list problems and I also needed to create a linked list out of an array of values. Say I also wanted to easily test if a function (such as reverseLinkedList) returns the correct list. I could use a class like this
Then, to test the above solution would be as easy as:
First, rewrite the reverse solution so that it takes a linkedList rather than just the head & so you can modify the head property of the list after it's been reversed:
const reverseLinkedList = (linkedlist) => {
let node = linkedlist.head;
let previous = null;
while(node) {
// save next or you lose it!!!
let save = node.next;
// reverse pointer
node.next = previous;
// increment previous to current node
previous = node;
// increment node to next node or null at end of list
node = save;
}
linkedlist.head = previous
return previous; // Change the list head !!!
}
Then you can run this test:
var inputList = new LinkedList([1,2,3,4])
var expectedReversedList = new LinkedList([4,3,2,1])
var actualReversedList = reverseLinkedList(inputList)
console.log(inputList.isEqualTo(actualReversedList))
Also, in terms of space and time complexity, since the above solution mutates the objects, it's O(1) space and since it iterates through the nodes just once, it's O(N) time complexity

How strict is the syntax of a for-loop

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()
);

Mysterious working of a Javascript - forth value returns no exception when array defined for three

The below code works fine in javascript
var items = [1,2,5]
for (var i = 0, item; item = items[i]; i++) {
console.log(item = items[i]);
}
OUTPUT : 1 2 5
I am not sure how this program works successfully
The forth item is undefined and what will happen in the last iteration.
Can we able to create a similar function in Java ?
items[3] at the end how it will be handled in the above function?
Two key things to start with:
First, in JavaScript, whenever you try to retrieve the value of an object property that doesn't exist (including an array entry), the result of the retrieval is the value undefined.
Second, when you use a value like a flag, as in an if statement or the "test" part of a for (or any other loop), etc., JavaScript with "coerce" whatever value you used to be boolean. [This is different from (say) Java, which requires that you only use boolean variables as that sort of flag.] Because JavaScript does this and it comes up a lot, we use the terms "truthy" (coerces to true) and "falsey" (coerces to false) to categorize values. The "falsey" values are 0, "", NaN, null, undefined, and of course false; all other values are truthy.
Okay, armed with that information, let's look at your loop:
The forth item is undefined and what will happen in the last iteration.
There are only three iterations. A for statement is made up of three expressions separated with ;, and a loop body. The expressions are the initialization, the test, and the increment:
// /--------------------------------initialization
// | /--------------- test
// | | /--- increment
// vvvvvvvvvvvvvvv vvvvvvvvvvvvvvv vvv
for (var i = 0, item; item = items[i]; i++) {
The loop is evaluated like this:
Do the initialization
Do the test
If the test was false, terminate
Do the body
Do the increment
Go back to step 2
The "test" part of your for loop is item = items[i], which is an assignment. The value of an assignment expression is the value being assigned. So when i is 3, that assignment is item = items[3] which is effectively item = undefined. That assignment has the value undefined, which is a falsey value, so the body of the loop isn't run a fourth time.
Can we able to create a similar function in Java ?
Yes, it looks almost identical other than that with Java, you use a type with the variables, and you can't use (just) the item = items[i] thing for the "test" part of the for (for the same reason you get an exception below).
items[3] at the end how it will be handled in the above function?
You don't have any function in your question. After the loop, in JavaScript, accessing items[3] would give you undefined (see above). In Java, it result in an ArrayIndexOutOfBoundsException.
Side note: The = in this line is an assignment, not a comparison:
console.log(item = items[i]);
If you meant to compare them, do this:
console.log(item == items[i]);
...which will give you the output
true
true
true
Here is what happens in your loop:
1. i = 0; item = 1; i = 1;
2. item = 2; i = 2;
3. item = 5; i = 3;
4. item = undefined; --> breaks the loop
Notice, that if you'd have items = [0,1,2], your loop would never be executed.
The code works fine as you have assignment in the for loop condition check
During the first iteration item is undefined but it executes the loop without termination as you assign the first value of array to item and it is no more undefined
Try it with comparision operator as item == items[i], you will find your loop no more executes even once.
When it comes outside of array i.e. items[3] which returns undefined and thus temp goes undefined and terminates the loop as in javascript undefined, null, 0 and false all are same.
This function wont work in Java as it would complain that it requires condition not the assignment in for loop.

While condition not getting terminated

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.

Determine the length of this Node-set?

Javascript for Mozilla:
while (result)
{
alert(result.childNodes[0].nodeValue);
//txt=txt+result.childNodes[0].nodeValue+"<br/>";
result=nodes.iterateNext();
}
This is intended to return a series of strings from an xml file. When I use the alert line, it alerts as expected with the proper strings in a series. The "txt" variable on the commented line is supposed to go to an innerHTML further down in the function. But Firebug keeps telling me that the result.childNodes[0] is undefined. Why would it be defined in the alert but not the next line?
I hope that's enough code to determine the problem...if not I will post more.
Thanks for help
[edit]
this is the definition of result:
var x=xmlDoc.responseXML;
var nodes=x.evaluate(path, x, null, XPathResult.ANY_TYPE, null);
var result=nodes.iterateNext();
I am retrieving XML
[edit]
okay I put the iterator in a for loop like this:
for (var i=0; i<2; i++)
{
var res=(xmlNodes.childNodes[0].nodeValue);
txt=txt+res+"<br/>";
xmlNodes=xmlQuery.iterateNext();
}
because I had a theory that once the iteration was null the loop would fail. So that's what happened--it worked until I set the loop one instance higher than the amount of nodes available. now I am trying to figure out how to get the "length" of the node-set. How do I do that?
I don't see any problems in the code you have shown so far. If childNodes[0] is undefined, then it has to be a text node or an empty node, and you should see an exception when trying to access a property such as nodeValue of childNodes[0] which is undefined. The exception will show up on alert or concatenation, or any other type of access.
This is the answer to your updated question.
now I am trying to figure out how to get the "length" of the node-set. How do I do that?
You can have the following types of node-sets returned from the evaluate function:
Iterators
Snapshots
First Nodes
I'll skip "first nodes" as that doesn't apply in this situation.
Iterators
With iterators, you only get an iterateNext() method for traversing nodes sequentially. Iterators refer to live nodes, meaning if the nodes in the document were to change while you are traversing the resultset, the iterator will become invalid.
Here's an example with using an iterator to go over each resulting node:
var results = doc.evaluate("expr", doc, null, ORDERED_SNAPSHOT, null);
var node;
while(node = results.iterateNext()) {
console.log(node);
}
If you want to use iterators, and find the number of matching results, a wrapper function that iterates through all nodes and returns them in an array might be useful.
function evaluateXPath(document, expression) {
var ANY_TYPE = XPathResult.ANY_TYPE;
var nodes = document.evaluate(expression, document, null, ANY_TYPE, null);
var results = [], node;
while(node = nodes.iterateNext()) {
results.push(node);
}
return results;
}
Get nodes as an array and loop the array:
var results = evaluateXPath(doc, "expr");
for(var i = 0; i < results.length; i++) {
console.log(results[i]);
}
Snapshots
Snapshots provide a static result of the nodes at the time of querying. Changes to the document will not affect this snapshot. Useful interfaces here will be the snapshotLength property, and snapshotItem(index) function.
Here's an example using a snapshot result:
var ORDERED_SNAPSHOT = XPathResult.ORDERED_NODE_SNAPSHOT_TYPE;
var results = doc.evaluate("expr", doc, null, ORDERED_SNAPSHOT, null);
for(var i = 0; i < results.snapshotLength; i++) {
var node = results.snapshotItem(i);
console.log(node);
}
See a working example.
It seems you are developing this for Firefox. Did you consider using E4X for this purpose? It provides a really easy interface for dealing with XML documents - for creating, manipulating, and querying.
now I am trying to figure out how to
get the "length" of the node-set. How
do I do that?
In XPath this is achieved using the standard XPath count() function.
count(someExpression)
evaluates to the number of nodes selected by someExpression.

Categories